[英]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
}
我希望主線程等待所有線程完成其工作。 請幫忙
處理此問題的最佳方法是使用Task.Run()
和Task.WhenAll()
,或使用Parallel.Invoke()
。
但是,如果您需要使用ThreadPool.QueueUserWorkItem
您可以按如下方式解決此問題:
CountdownEvent
實例,該實例初始化的計數等於您要等待的線程數。 (在下面的示例代碼中,此類稱為ThreadData
。)TaskCallBack()
方法中,當方法完成時調用CountdownEvent.Signal()
。CountdownEvent.Wait()
等待所有線程完成。將所有這些放在一個可編譯的控制台應用程序中:
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);
}
}
ThreadData.Index
屬性僅用於標識Console.WriteLine()
調用中的每個線程。
注意:在實際代碼中,即使線程拋出異常,始終發出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();
}
}
就像@Ackdari 在他的評論中提到的那樣,您可以使用Task.Run 。 但是您不需要await關鍵字。 只需使用任務創建一個集合並等待它。
例子:
// 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());
這樣你也可以使用你自己的方法來運行任務。 例子:
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.