|
分類:[C#]
Windows 10, 日本語 (64bit)の環境でVisual Studio 2015を使用しています。
async/awaitを用いた非同期処理を始めて実装しようとしているのですが、Windowsフォームアプリケーションで作成したコードでTask.WaitAllが実行されていない?実行完了しても抜けない?問題に悩まされています。
処理が5分ほどかかる複数の処理を同時並列し、すべて終わるまで待つというコードを作成しようとしており、処理をひとつづつtaskListに格納し、Task.WaitAll(taskList.ToArray());で一度に実行することを意図しています。
まずは、成功例から。下記のコンソールアプリケーションではタスクC,D,E,F,Gを非同期で実行し、すべての処理完了後、WaitAllを抜けます。
Program.cs
var process2 = new TestRunner();
process2.RunTest();
TestRunner.cs
private DoLongTimeWorkers DoWork = new DoLongTimeWorkers();
public void RunTest()
{
ExecuteLongWork("[Single Task] Process A:", 5, 590, 1000);
ExecuteLongWork("[Single Task] Process B:", 6, 690, 1000);
var taskList = new List<Task<string>>();
taskList.Add(ExecuteLongWorkAsync("[Multi Task] Process C:", 12, 990, 3000));
taskList.Add(ExecuteLongWorkAsync("[Multi Task] Process D:", 26, 520, 8000));
taskList.Add(ExecuteLongWorkAsync("[Multi Task] Process E:", 18, 800, 1000));
taskList.Add(ExecuteLongWorkAsync("[Multi Task] Process F:", 21, 600, 6000));
taskList.Add(ExecuteLongWorkAsync("[Multi Task] Process G:", 58, 200, 6000));
Task.WaitAll(taskList.ToArray());
}
private async Task<string> ExecuteLongWorkAsync(string processName, int repeatTime, int intervalTime, int stableTime)
{
var result = await Task.Run(() => DoWork.DoLongTimeWork(processName, repeatTime, intervalTime, stableTime));
return result;
}
DoLongTimeWorkers.cs
class DoLongTimeWorkers
{
public string DoLongTimeWork(string processName, int repeatTime, int intervalTime, int stableTime)
{
string result;
for (int i = 1; i <= repeatTime; i++)
{
Console.WriteLine($"{processName} {i}/{repeatTime} ===== ");
Thread.Sleep(intervalTime);
}
result = "Completed";
Thread.Sleep(stableTime);
return result;
}
}
上記のコードを実行するとTask AとBをシリアルに実行したあと、C-Gを同時に、非同期で実行できることが確認できます。
さて、このTestRunner.csとDoLongTimeWorkers.csを使いまわしてWindows Form Applicationに組み込だのですが、Task.WaitAll実行後処理が次に進みません。
ステップ実行する限り、Task C-Gが実行されないように見えます。Windows Form Applicationの場合になにか足りないのでしょうか。または上記コードは間違っていてたまたまConsole Applicationの場合は動いていただけなのでしょうか。
Form1.cs
private void button1_Click(object sender, EventArgs e)
{
var ts = new TestRunner();
ts.RunTest(this.textBox1);
}
TestRunner.cs (TextBoxコントロールを渡す以外はConsole Applicationと同じ)
DoLongTimeWorkers.cs (渡されたTextBoxコントロールにConsole.WriteLineの結果を書き込む以外はConsole Applicationと同じ)
もしご存知の方がいらっしゃいましたらよろしくお願いします。
|