繁体   English   中英

后台工作人员表现怪异?

[英]Backgroundworker acting weird?

我目前正在处理一个多线程项目,该项目涉及多个并行运行的耗时任务。

每个任务都记录在同一个文件中,我需要保持整洁(以正确的顺序),所以我找到了一种“逐个任务”记录的方法:

  • 当任务必须写入日志文件时,我将日志写入字典: _logList[id].Add(message)
  • 此字典具有键 = ThreadID,值 = 具有此 ID 的工作者的日志(字符串列表)
  • ThreadID 来自Thread.CurrentThread.ManagedThreadId

下面是我如何启动我的 BackgroundWorkers:

foreach (MyTask task in List<MyTask> tasks)
{
   BackgroundWorker bg = new BackgroundWorker();
   bg.DoWork += bgworker_DoWork;
   bg.RunWorkerCompleted += bgworker_RunWorkerCompleted;
   List<object> arguments = new List<object>() { task, args1 };
   bg.RunWorkerAsync(arguments);
}

bgworker_DoWork 委托是耗时的任务,写日志。

然后,当一个任务结束时,BackgroundWorker 运行委托 bgworker_RunWorkerCompleted,它基本上以正确的顺序结束任务并写入相应的日志:

Log.FlushWrite((int)result[2]); -- result[2] contains the threadId to flush

而 FlushWrite 只将 threadId 的日志列表写入日志文件:

WriteMessageToFile(_logList[id]);

大多数情况下,这是有效的。 但有时,我会看到一种奇怪的行为:

  • 多个任务使用相同的 ThreadID
  • 当 ThreadID X 的第一个任务 N 结束时,它调用 RunWorkerCompleted 委托,并刷新其日志 + 仅刷新 ThreadID X 的下一个任务 N+1 的一部分(因为任务尚未结束)
  • 当任务N+1真正结束的时候,把剩余的日志flush了再写,但是日志文件因为不整洁,乱七八糟!

我知道托管线程 id 可能会被回收和重用,但是发生这种情况的唯一方法是当运行的 BackgroundWorker 尚未调用RunWorkerCompleted时该线程已经被重用(对DoWork新调用)

我对吗? 这种情况有什么我不明白的地方吗?

也许在这种情况下使用 ManagedThreadId 作为字典的键是一种不好的做法?

谢谢你的帮助 :)

我发现了我的问题:在FlushWrite操作期间,执行了锁定。 如果这个worker等待的时间太长,另一个worker可能会写到同一个ThreadID,导致这种情况下的flush操作不一致。

通过使用另一本字典解决,仅用于刷新“完整的工人”。

还重写了代码以将BackGroundWorker更改为Task.Run 谢谢 :)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM