最初に何かを片付けましょう。
- このために個別のスレッドを作成しないでください。スレッドは高価なリソースです。代わりに、スレッド プーリング手法を使用してください。
Thread.Join
、WaitHandle.WaitOne
、またはその他のブロック メカニズムを呼び出して UI スレッドをブロックしないでください。
TPLでこれを行う方法は次のとおりです。
private void repairClientsToolStripMenuItem_Click(object sender, EventArgs e)
{
if (machineList.Count() != 0)
{
// Start the parent task.
var task = Task.Factory.StartNew(
() =>
{
foreach (string ws in machineList)
{
string capture = ws;
// Start a new child task and attach it to the parent.
Task.Factory.StartNew(
() =>
{
fixClient(capture);
}, TaskCreationOptions.AttachedToParent);
}
}, TaskCreationOptions.LongRunning);
// Define a continuation that happens after everything is done.
task.ContinueWith(
(parent) =>
{
// Code here will execute after the parent task including its children have finished.
// You can safely update UI controls here.
}, TaskScheduler.FromCurrentSynchronizationContext);
}
else
{
MessageBox.Show("Please import data before attempting this procedure");
}
}
ここで行っているのは、それ自体が子タスクを起動する親タスクを作成することです。TaskCreationOptions.AttachedToParent
子タスクを親タスクに関連付けるために使用していることに注意してください。ContinueWith
次に、親とそのすべての子が完了した後に実行される親タスクを呼び出します。TaskScheduler.FromCurrentSynchronizationContext
UIスレッドで継続を発生させるために使用します。
を使用した代替ソリューションを次に示しParallel.ForEach
ます。少しクリーンなソリューションであることに注意してください。
private void repairClientsToolStripMenuItem_Click(object sender, EventArgs e)
{
if (machineList.Count() != 0)
{
// Start the parent task.
var task = Task.Factory.StartNew(
() =>
{
Parallel.Foreach(machineList,
ws =>
{
fixClient(ws);
});
}, TaskCreationOptions.LongRunning);
// Define a continuation that happens after everything is done.
task.ContinueWith(
(parent) =>
{
// Code here will execute after the parent task has finished.
// You can safely update UI controls here.
}, TaskScheduler.FromCurrentSynchronizationContext);
}
else
{
MessageBox.Show("Please import data before attempting this procedure");
}
}