0

如何知道循环中的所有工作人员何时完成?以及如何在所有工人之后“执行” bw_RunWorkerCompleted。我尝试了几种方法,但都失败了。主要工人总是先完成。

.Net 3.5

http://pastebin.com/kMmajq6f

using System;
using System.ComponentModel;
using System.Threading;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {

            BackgroundWorker bw = new BackgroundWorker();
            bw.DoWork += new DoWorkEventHandler(bw_DoWork);
            bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
            bw.WorkerSupportsCancellation = true;
            bw.WorkerReportsProgress = true;

            bw.RunWorkerAsync();

            Console.ReadLine();

        }

        static void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            Console.WriteLine("All");
        }

        static void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            for (int i = 0; i < 10; i++)
            {
                BackgroundWorker inBW = new BackgroundWorker();
                inBW.DoWork += new DoWorkEventHandler(inBW_DoWork);
                inBW.RunWorkerCompleted += new RunWorkerCompletedEventHandler(inBW_RunWorkerCompleted);

                inBW.RunWorkerAsync(i.ToString());
            }
        }

        static void inBW_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            Console.WriteLine(e.Result as String);
        }

        static void inBW_DoWork(object sender, DoWorkEventArgs e)
        {
            Thread.Sleep(new Random().Next(1000, 5000));

            e.Result = e.Argument as string;
        }
    }
}
4

3 回答 3

3
static int workerCount = 11; // one more for the main BW
static int completedWorkerCount = 0;

static void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    Console.WriteLine("All");
    updateAllWorkersProgress()
}

static void inBW_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
     Console.WriteLine(e.Result as String);
     updateAllWorkersProgress();
}

static void updateAllWorkersProgress()
{
     if (++completedWorkerCount == workerCount)
     {
           Console.WriteLine("Everything completed");
     }
}
于 2012-09-26T15:24:03.710 回答
2

就像史蒂夫建议的那样,使用任务。但是,如果您不能随意 - 然后为每个子工作人员创建一个等待句柄,并在主 bg 工作人员中等待所有这些。

您需要有一个ManualResetEvents列表/数组作为成员变量,并为每个子工作人员传递一个。一旦完成,每个子工作者都会发出一个事件信号。只有在收到所有信号后,主 bg-worker 才会完成(使用WaitAll

请参阅此 - MSDN 上的手动重置事件和 WaitAll

于 2012-09-26T15:32:47.300 回答
2

一旦DoWork事件处理程序返回,就会调用RunWorkerCompleted事件处理程序。在这种情况下,bw_DoWork 方法会在它分离出 10 个额外的 BackgroundWorker 后返回。

我打算建议您为您的案例使用 CountdownEvent,但意识到您使用的是 .Net 3.5。在这种情况下,您可以使用Pulse 和 Wait创建类似的内容。

于 2012-09-26T15:37:36.357 回答