Let us get something out of the way first.
- Do not create individual threads for this. Threads are an expensive resource. Instead use thread pooling techniques.
- Do not block the UI thread by calling
Thread.Join
, WaitHandle.WaitOne
, or any other blocking mechanism.
Here is how I would do this with the 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");
}
}
What I am doing here is creating a parent task that will itself spin up child tasks. Notice that I use TaskCreationOptions.AttachedToParent
to associate the child tasks with their parent. Then on the parent task I call ContinueWith
which gets executed after the parent and all of its children have completed. I use TaskScheduler.FromCurrentSynchronizationContext
to get the continuation to happen on the UI thread.
And here is an alternate solution using Parallel.ForEach
. Notice that it is a little bit cleaner solution.
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");
}
}