[英]In .Net/C# is there a way to either wait for or get notified when all my worker threads have completed processing?
我有一个.Net C#应用程序,试图在其中生成多个线程。 该应用程序用于性能测试,是一个简单的控制台应用程序。 产生线程的部分工作正常。
我正在寻找的是正确的机制,要么在所有线程完成执行时收到通知,要么在我的应用程序中等待所有线程完成。 此时,我将打印出结果摘要。
String testName = "foo";
String fullTestName;
// Iterate and create threads
for (int index = 0; index < numberOfThreads; index++)
{
fullTestName = String.Format("{0}Thread{1}", testName, index);
Thread thread = new Thread(() => PerformanceTest(fullTestName, index, numberOfRows, testToRun));
thread.IsBackground = true;
thread.Name = fullTestName;
thread.Start();
}
void PerformanceTest(String testName, int iterationNumber, long numberOfRows)
{
// Insert a bunch of rows into DB
}
我已经看过使用RegisterWaitForSingleObject(),但无法弄清楚如何在我的方案中使用它。
您可以使用Task
而不是Thread
。 它为您提供了比并行操作更高的抽象级别,以及一个不错的同步方法库。 例如,您可以使用以下命令等待所有任务完成。
IEnumerable<Task> BeginParallelTests(string fullTestName, int numberOfThreads)
{
for(var index = 0; index < numberOfThreads; index++)
{
yield return Task.Factory.StartNew(
() => PerformanceTest(fullTestName, index, numberOfRows));
}
}
然后,在您的主要方法中,您可以只使用:
Task.WaitAll(BeginParallelTests(testName, numberOfThreads));
(也许您必须使用类似ToArray()
来强制枚举BeginParallelTest
方法)
尝试使用任务而不是线程。
class Program
{
static Random random = new Random();
static void Main(string[] args)
{
TaskFactory taskfactory = new TaskFactory(TaskCreationOptions.LongRunning, TaskContinuationOptions.None);
var tasks = new List<Task>();
for (int i = 0; i < 10; i++)
{
var task = taskfactory.StartNew(() => { DoWork("Thread " + i); });
Console.WriteLine(string.Format("Started thread {0}", i));
tasks.Add(task);
}
Task.WaitAll(tasks.ToArray());
}
static void DoWork(string threadname)
{
int sleeptime = random.Next(10) * 1000;
Console.WriteLine(string.Format("Thread {0} sleeping {1}ms", threadname, sleeptime));
Thread.Sleep(sleeptime);
}
}
我正在寻找的是正确的机制,要么在所有线程完成执行时收到通知,要么在我的应用程序中等待所有线程完成。
最简单的方法是跟踪线程(使用数组),然后依次在每个线程上调用Thread.Join
:
Thread[] threads = new Thread[numberOfThreads];
for (int index = 0; index < numberOfThreads; index++)
{
string fullTestName = String.Format("{0}Thread{1}", testName, index);
Thread thread = new Thread
(() => PerformanceTest(fullTestName, index, numberOfRows, testToRun));
thread.IsBackground = true;
thread.Name = fullTestName;
thread.Start();
threads[index] = thread;
}
// Wait for everything to finish
foreach (Thread thread in threads)
{
thread.Join();
}
使用任务并行库是另一种选择,但是您一次可能没有很多线程在运行-这样可能会更好地执行,但是如果您要衡量特定数量的线程会发生什么,您可以需要真正地自己启动它们。
另一个建议是使用PLinq或新的asynch关键字提高抽象水平。
这是一个PLinq示例,该示例抽象了从开发人员到框架的线程。
string testName = "foo";
string fullTestName;
var testIterations = 100;
Enumerable.Range(0, testIterations).AsParallel().ForAll(i=>
{
PerformanceTest(testName,i,numberOfRows);
});
void PerformanceTest(String testName, int iterationNumber, long numberOfRows)
{
// Insert a bunch of rows into DB
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.