C# 在.Net/C中,有没有一种方法可以在我的所有工作线程完成处理后等待或得到通知?

C# 在.Net/C中,有没有一种方法可以在我的所有工作线程完成处理后等待或得到通知?,c#,.net,multithreading,C#,.net,Multithreading,我有一个.NETC#应用程序,试图在其中生成多个线程。 该应用程序用于性能测试,是一个简单的控制台应用程序。 用于生成线程的部件工作正常 我要寻找的是一种正确的机制,即在所有线程完成执行时收到通知,或者在我的应用程序中等待所有线程完成。 在这一点上,我将打印出结果的摘要 下面是我的代码片段的样子: String testName=“foo”; 字符串fullTestName; //迭代并创建线程 for(int index=0;indexPerformanceTest(fullTestName、

我有一个.NETC#应用程序,试图在其中生成多个线程。 该应用程序用于性能测试,是一个简单的控制台应用程序。 用于生成线程的部件工作正常

我要寻找的是一种正确的机制,即在所有线程完成执行时收到通知,或者在我的应用程序中等待所有线程完成。 在这一点上,我将打印出结果的摘要

下面是我的代码片段的样子:
String testName=“foo”;
字符串fullTestName;
//迭代并创建线程
for(int index=0;indexPerformanceTest(fullTestName、index、numberOfRows、testToRun));
thread.IsBackground=true;
thread.Name=fullTestName;
thread.Start();
}
void PerformanceTest(字符串testName、int iterationNumber、long numberOfRows)
{
//在数据库中插入一组行
}
我已经研究过如何使用RegisterWaitForSingleObject(),但不知道如何在我的场景中使用它

我要寻找的是一种正确的机制,即在所有线程完成执行时收到通知,或者在我的应用程序中等待所有线程完成

最简单的方法就是跟踪线程(使用数组),然后依次调用每个线程:

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();
}
Thread[]threads=新线程[numberOfThreads];
for(int index=0;indexPerformanceTest(fullTestName、index、numberOfRows、testToRun));
thread.IsBackground=true;
thread.Name=fullTestName;
thread.Start();
线程[索引]=线程;
}
//等待一切结束
foreach(线程中的线程)
{
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();
}
Thread[]threads=新线程[numberOfThreads];
for(int index=0;indexPerformanceTest(fullTestName、index、numberOfRows、testToRun));
thread.IsBackground=true;
thread.Name=fullTestName;
thread.Start();
线程[索引]=线程;
}
//等待一切结束
foreach(线程中的线程)
{
thread.Join();
}

使用Task Parallel Library是另一种选择,但是一次运行的线程可能不多,这样可能会更好,但是如果您试图测量特定数量的线程会发生什么,您需要自己真正地启动它们。

另一个建议是使用PLinq或新的异步关键字提高抽象级别

下面是一个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
}

另一个建议是使用PLinq或新的异步关键字提高抽象级别

下面是一个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
}

您可以使用
任务
而不是
线程
。它为您提供了比并行操作更高级别的抽象,并提供了一个很好的同步方法库。例如,您可以使用以下命令等待所有任务完成

IEnumerable<Task> BeginParallelTests(string fullTestName, int numberOfThreads)
{
    for(var index = 0; index < numberOfThreads; index++)
    {
        yield return Task.Factory.StartNew(
            () => PerformanceTest(fullTestName, index, numberOfRows));
    }
}

(可能您必须使用类似于
ToArray()
的方法来强制执行
BeginParallelTest
方法的枚举)

您可以使用
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));
    }
}

(可能您必须使用类似于
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);
    }
}
类程序
{
静态随机=新随机();
静态void Main(字符串[]参数)
{
TaskFactory TaskFactory=新建TaskFactory(TaskCreationOptions.LongRunning,TaskContinuationOptions.None);
var tasks=新列表();
对于(int i=0;i<10;i++)
{
var task=taskfactory.StartNew(()=>{DoWork(“线程”+i);});
WriteLine(string.Format(“启动线程{0}”,i));
任务。添加(任务);
}
Task.WaitAll(tasks.ToArray());
}
静态void DoWork(字符串threadname)
{
int sleeptime=random.Next(10)*1000;
WriteLine(string.Format(“Thread{0}sleepping{1}ms”,threadname,sleeptime));
睡眠(睡眠时间);
}
}

尝试使用任务而不是线程

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);
    }
}
类程序
{
静态随机=新随机();
静态void Main(字符串[]参数)
{
TaskFactory TaskFactory=新建TaskFactory(TaskCreationOptions.LongRunning,TaskContinuationOptions.None);
var tasks=新列表();
对于(int i=0;i<10;i++)
{
var task=taskfactory.StartNew(()=>{DoWork(“线程”+i);});
Console.WriteLine(string.Format(“已启动”)threa