C# BackgroundWorker 并行调用 DoWorkEventHandler
这是我的情况:
我有一个启动BackgroundWorkers的ThreadManager;我订阅 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”,并在几分钟后开始得到“Pong”。
我在这里缺少什么吗?
编辑:
我本身不使用“控制台”,而是使用异步记录器(即示例)。我仔细观察了“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
}
}
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 the 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
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您缺少以下内容:
DoWork
事件的订阅者不是并行调用,而是以串行方式调用,即首先使用 PING 调用处理程序,然后使用 PONG 调用处理程序。因此,当 PING 处理程序需要 3 分钟时,PONG 处理程序将在您调用 RunWorkerAsync 三分钟后执行。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 calledRunWorkerAsync
.DoWork
是一个普通事件,通过多播,它是一个顺序调用链,BackgroundWorker
不会改变这一点。简而言之,将多个事件处理程序挂起该事件的情况并不常见。
所以是的,这是非常自然的,因为您在评论中特别提到第一个事件处理程序运行 2-3 分钟,然后是的,第二个事件处理程序将在几分钟后启动。
DoWork
is a normal event, and with multicast, it's a sequential call-chain, andBackgroundWorker
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.
据我所知,Console.Out.Write 是缓冲的。尝试WriteLine。
As far as I know, Console.Out.Write is buffered. Try WriteLine.
这可能不相关,但建议重写派生类中的
OnXXX
方法,而不是订阅自己的事件。因此,不要忘记调用
base.OnDoWork()
。This might be unrelated, but it's recommended to override
OnXXX
methods in derived classes rather then subscribe to own events. Thus,And do not forget to call
base.OnDoWork()
.