c#后台工作并行调用DoWorkEventHandler

本文关键字:调用 DoWorkEventHandler 并行 工作 后台 | 更新日期: 2023-09-27 17:50:23

我的情况是:
我有一个线程管理器启动后台工作;我订阅了doWork事件来记录里面的东西。我还订阅了BackgroundWorker本身的doWork事件来处理东西。嗯,第一个订阅在第二个订阅之后触发事件。

class ThreadManager
{
  //(...)
  for (int i = 0; i<100; i++)
  {
   myWorker wk = new myWorker();
   wk.DoWork += new DoWorkEventHandler(wk_DoWork);
  }
  //(...)
  public void wk_DoWork(object sender, DoWorkEventArgs e)
    {
      Console.Out.Write("PONG");
      //(...) Workers Management logic (Pooling, priority, etc.)
    }
}

internal class myWorker : : BackgroundWorker
{
   //(...)
   DoWork += new DoWorkEventHandler(DoMe);
   //(...)
   void DoMe(object sender, DoWorkEventArgs e)
   {
      Console.Out.Write("PING");
      //(...) Run a 2-3mn file reading process           
   }
}

由于某种原因,我连续收到所有"ping",几分钟后就开始收到"Pongs"。

我是不是漏掉了什么?

EDIT:
我不使用"控制台"本身,而是使用异步日志记录器(这是示例)。我仔细观察了"PONG"行上的调试过程,在"PING"启动后,它没有被击中。

我的解决方案:这正是我希望避免的额外代码,但我最终无法减少痛苦。所以这里是,对于那些有同样的问题和绊倒在这篇文章:

class ThreadManager
{
  //(...)
  for (int i = 0; i<100; i++)
  {
   myWorker wk = new myWorker();
   wk.StartedEvent += new myWorker.startDelegate(wk_Started);
  }
  //(...)
  public void wk_Started(params-if-needed)
    {
      Console.Out.Write("PONG");
      //(...) Do Stuff
    }
}   
internal class myWorker : BackgroundWorker
{
   public delegate void startDelegate(string ID);
   public event startDelegate StartedEvent;
   protected override void OnDoWork(DoWorkEventArgs e)
   {
      StartedEvent(ID); //put whatever parameter suits you or nothing
      base.OnDoWork(e);
      e.Result = e.Argument;
      Console.Out.Write("PING");
      //(...) Do Stuff     
   }
}

c#后台工作并行调用DoWorkEventHandler

您缺少以下内容:
DoWork事件的订阅者不是以并行方式调用的,而是以串行方式调用的,即首先使用PING处理程序,然后使用PONG处理程序。因此,当PING处理程序需要3分钟时,PONG处理程序将在调用RunWorkerAsync后3分钟执行。

DoWork是一个正常事件,使用组播时,它是一个顺序的调用链,BackgroundWorker不改变这一点。

简而言之,在一个事件上挂起多个事件处理程序是不典型的。

所以,是的,这是非常自然的,因为您在评论中特别提到第一个事件处理程序运行2-3分钟,然后是的,第二个事件处理程序将在几分钟后启动。

据我所知,Console.Out.Write是缓冲的。尝试WriteLine。

这可能无关,但建议在派生类中重写OnXXX方法,而不是订阅自己的事件。因此,

class MyWorker : BackgroundWorker
{
    protected override void OnDoWork(...) { .... }
}

不要忘记调用base.OnDoWork()