[英]how to make Wait until all threads finished it's work from threadpool in c#
for (int task = 0; task < 20; task++)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(TaskCallBack), new object[] { filepath1, filepath2,
filepath3 });
}
public static void TaskCallBack(object state)
{
object[] array = state as object[];
string filea = Convert.ToString(array[0]);
string fileb = Convert.ToString(array[1]);
string filec = Convert.ToString(array[2]);
//something below
}
I want main thread to be waited until all threads finishes its work.我希望主线程等待所有线程完成其工作。 Please help请帮忙
The best way to handle this would be to use Task.Run()
and Task.WhenAll()
, or to use Parallel.Invoke()
.处理此问题的最佳方法是使用Task.Run()
和Task.WhenAll()
,或使用Parallel.Invoke()
。
However, if you need to use ThreadPool.QueueUserWorkItem
you can solve this issue as follows:但是,如果您需要使用ThreadPool.QueueUserWorkItem
您可以按如下方式解决此问题:
CountdownEvent
initialised with a count equal to the number of threads you want to wait for.此数据应包括一个CountdownEvent
实例,该实例初始化的计数等于您要等待的线程数。 (In the sample code below, this class is called ThreadData
.) (在下面的示例代码中,此类称为ThreadData
。)TaskCallBack()
methods, call CountdownEvent.Signal()
when the method has completed.在TaskCallBack()
方法中,当方法完成时调用CountdownEvent.Signal()
。CountdownEvent.Wait()
to wait for all the threads to complete.在主线程内部,启动所有线程池线程,然后调用CountdownEvent.Wait()
等待所有线程完成。Putting this all together in a compilable console app:将所有这些放在一个可编译的控制台应用程序中:
using System;
using System.Threading;
namespace CoreConsole
{
public sealed class ThreadData
{
public ThreadData(CountdownEvent countdown, int index)
{
Countdown = countdown;
Index = index;
}
public CountdownEvent Countdown { get; }
public int Index { get; }
}
public static class Program
{
static void Main()
{
int n = 20;
var countdown = new CountdownEvent(n);
for (int task = 0; task < n; task++)
{
ThreadPool.QueueUserWorkItem(TaskCallBack, new ThreadData(countdown, task));
}
Console.WriteLine("Waiting for all threads to exit");
countdown.Wait();
Console.WriteLine("Waited for all threads to exit");
}
public static void TaskCallBack(object state)
{
var data = (ThreadData) state;
Console.WriteLine($"Thread {data.Index} is starting.");
Thread.Sleep(_rng.Next(2000, 10000));
data.Countdown.Signal();
Console.WriteLine($"Thread {data.Index} has finished.");
}
static readonly Random _rng = new Random(45698);
}
}
The ThreadData.Index
property is just used to identify each thread in the Console.WriteLine()
calls. ThreadData.Index
属性仅用于标识Console.WriteLine()
调用中的每个线程。
Note: In real code, it is important to always signal the Countdown
event, even if the thread throws an exception - so you should wrap the code in a try/finally like so:注意:在实际代码中,即使线程抛出异常,始终发出Countdown
事件信号很重要 - 因此您应该将代码包装在 try/finally 中,如下所示:
public static void TaskCallBack(object state)
{
var data = (ThreadData)state;
try
{
// Do work here.
Console.WriteLine($"Thread {data.Index} is starting.");
Thread.Sleep(_rng.Next(2000, 10000));
Console.WriteLine($"Thread {data.Index} has finished.");
}
finally
{
data.Countdown.Signal();
}
}
Like @Ackdari mentioned in his comment, you could use Task.Run .就像@Ackdari 在他的评论中提到的那样,您可以使用Task.Run 。 But you don't need the await keyword.但是您不需要await关键字。 Just create a collection with the tasks and wait for it.只需使用任务创建一个集合并等待它。
Example:例子:
// Create a list that will hold the tasks
List<Task> tasks = new List<Task>;
// Create the tasks
for (int taskId = 0; taskId < 20; task++)
{
tasks.Add(Task.Run(() => { TaskCallBack(new object[] { filepath1, filepath2, filepath3 }); }));
}
// Wait for ALL tasks to complete
Task.WaitAll(tasks.ToArray());
That way you could also use your own method that will be run by the task.这样你也可以使用你自己的方法来运行任务。 Example:例子:
public static void ReplaceWithABetterName(string[] filePaths)
{
string filea = filePaths[0);
string fileb = filePaths[1];
string filec = filePaths[2];
//do stuff
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.