ファイルコピースレッドが実行されている間、uiスレッドを取得してuiを更新できません。私の最終目標は、大きなファイルのコピーが最終的に完了して、プログラムがフリーズしていないことをユーザーに知らせるまでアニメーションを回転させ続けることです。これは、非常にシンプルなサーバーのファイルコピープログラムです。l versC#マルチスレッドの問題
私が間違っていることを誰かに教えてもらえますか?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.IO;
using System.Threading.Tasks;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void ResetProgress()
{
lblStep1.Image = null;
}
private void SetupProgress()
{
lblStep1.Image = global::animation1.Properties.Resources.animation;
}
private void fileCopy()
{
File.Copy("large file source", "large file destination", true);
}
private void Form1_Load(object sender, EventArgs e)
{
lblStep1.Image = global::animation1.Properties.Resources.animation;
}
private async void button1_Click(object sender, EventArgs e)
{
SetupProgress();
await Task.Run(() => fileCopy());
ResetProgress();
}
private void btnStop_Click(object sender, EventArgs e)
{
// unhandled currently
}
}
}
*オリジナルバージョン*
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.IO;
using System.Threading.Tasks;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private Thread workItemsProducerThread;
private Thread workItemsCopyThread;
public Form1()
{
InitializeComponent();
}
private void ResetProgress()
{
lblStep1.Image = null;
}
private void SetupProgress()
{
this.BeginInvoke((MethodInvoker)delegate()
{
lblStep1.Image = global::animation1.Properties.Resources.animation;
});
}
private void fileCopy()
{
File.Copy("Large file source", "Large file destination", true);
this.BeginInvoke((MethodInvoker)delegate()
{
MessageBox.Show("Done");
});
}
private void Form1_Load(object sender, EventArgs e)
{
lblStep1.Image = global::animation1.Properties.Resources.animation;
}
private void btnStart_Click(object sender, EventArgs e)
{
this.workItemsProducerThread = new Thread(new ThreadStart(this.SetupProgress));
this.workItemsProducerThread.IsBackground = true;
this.workItemsProducerThread.Start();
this.SetupProgress();
this.workItemsCopyThread = new Thread(new ThreadStart(this.fileCopy));
this.workItemsCopyThread.IsBackground = true;
this.workItemsCopyThread.Start();
while (workItemsCopyThread.IsAlive)
{
Thread.Sleep(1000); // wait
}
MessageBox.Show("Done");
}
private void btnStop_Click(object sender, EventArgs e)
{
if (this.workItemsProducerThread != null)
{
this.workItemsProducerThread.Abort();
lblStep1.Image = global::animation1.Properties.Resources.animation;
}
}
private void btnTest_Click(object sender, EventArgs e)
{
fileCopy();
}
}
}
このoldyスタイルを試してみてください。それは悪い考えです。 –
私はこれらの提案を試しましたが、症状は同じです。私は、メインUIからSetupProgressを実行し、begininvokeを呼び出しただけで置き換えようとしましたが、動作は変更されません。 – Jay
@Jayその理由は、コードが複雑すぎるためです。あなたはスレッド、呼び出し、または中止は必要ありません。 Henk Holtermanの答えは、組み込みのTask.Runとasync/awaitを使ってこれを書くのが簡単であることを示しています。 –