开发者

C# BackgroundWorker Parallel Call to DoWorkEventHandler

Here is my situation :

I have a ThreadManager launching BackgroundWorkers; I subscribe to the doWork event to Log stuff in it. I also subscribo to the doWork event in the BackgroundWorker itself to process stuff. Well, The first subscription raises the event way after the second one was raised.

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           
   }
}

For some reason, I am getting all "Pings" in a row, and start getting Pongs only a few minutes after.

Is there something I am missing here ?

EDIT :

I do not use "Console" per se, but asynchronous loggers (that was for the example). I have been careful to watch t开发者_JAVA百科he debug process at the "PONG" line, and it is not hit way after the "PING"s has been launched.

MY SOLUTION : This is exactly the extra code I was hoping to avoid, but I could'nt cut the pain finally. So here it is, for those having the same issu and stumbling on this post :

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     
   }
}


You are missing the following:
The subscribers to the DoWork event are not called in parallel but in a serial manner, i.e. first your handler with PING and after that the handler with PONG. So, when the PING handler takes 3 minutes, the PONG handler will be executed three minutes after you called RunWorkerAsync.


DoWork is a normal event, and with multicast, it's a sequential call-chain, and BackgroundWorker does not change that.

In short, it's not typical to hang multiple event handlers off of that event.

So yes, it's perfectly natural, since you specifically mention in your comments that the first event handler runs for 2-3 minutes, then yes, the second event handler will start a few minutes later.


As far as I know, Console.Out.Write is buffered. Try WriteLine.


This might be unrelated, but it's recommended to override OnXXX methods in derived classes rather then subscribe to own events. Thus,

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

And do not forget to call base.OnDoWork().

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜