想要使用线程分解一个非常繁重的函数,并在工作完成时显示一个消息框。
以下是类似的代码:
for (int index = 0; index < tests.Count; index/=3)
{
System.Threading.Thread t =
new System.Threading.Thread(
() => SomeFunction(tests.GetRange(start, 3)));
t.Start();
}
想要在所有这些线程完成执行并完成整个工作后显示一个消息框。我该怎么做? 加入将无法正常工作,因为它会导致不使用线程。
答案 0 :(得分:7)
如果你在.Net4.0 +中,请扔掉旧学校的主题。使用Task paralell库。
var uiContext = TaskScheduler.FromCurrentSynchronizationContext();
var tasks = ...;//Start tasks
Task.Factory.ContinueWhenAll(tasks, antecedents =>
{
//Show messagebox here
},CancellationToken.None,TaskContinuationOptions.None,uiContext);
使用ContinueWhenAll
异步等待,并使用FromCurrentSynchronizationContext
在UIThread中执行回调。
答案 1 :(得分:3)
如果使用任务而不是线程,则更容易:
var tasks = new List<Task>();
for (int index = 0; index < tests.Count; index/=3)
{
var task = Task.Factory.StartNew(() => SomeFunction(tests.GetRange(start, 3)));
tasks.Add(tasks);
}
Task.WaitAll(tasks.ToArray());
MessageBox.Show("Done!");
如果你真的想使用线程,可以选择使用等待句柄:
var waitHandles = new List<EventWaitHandle>();
for (int index = 0; index < tests.Count; index/=3)
{
var waitHandle = new ManualResetEvent(false);
waitHandles.Add(waitHandle);
System.Threading.Thread t =
new System.Threading.Thread(
() =>
{
SomeFunction(tests.GetRange(start, 3));
waitHandle.Set();
});
t.Start();
}
WaitHandle.WaitAll(waitHandles.ToArray());
MessageBox.Show("Done!");
请注意,如果您在UI线程上调用此方法,则UI将被冻结,直到所有线程完成。如果您想避免这种情况,更好的选择是使用Task.Factory.ContinueWhenAll
,如Sriram Sakthivel的回答所示。
index/=3
部分吗?如果test.Count > 0
... ,它将导致循环永远运行
答案 2 :(得分:1)
为什么你不使用Parallel.Foreach()
代替它,它会自动等待所有。像这样:
Parallel.ForEach(Enumerable.Range(1, 10), i =>
{
Console.WriteLine("{0} - {1}", i, GetTotal());
});