C# 背景工作人员的行为怪异?

C# 背景工作人员的行为怪异?,c#,multithreading,backgroundworker,C#,Multithreading,Backgroundworker,我目前正在从事一个多线程项目,涉及几个并行运行的耗时任务 每个任务都记录在同一个文件中,我需要保持文件整洁(顺序正确),因此我找到了一种“逐个任务”记录的方法: 当任务必须写入日志文件时,我会将日志写入字典:\u logList[id]。添加(消息) 此字典的Key=ThreadID,Value=worker的日志(字符串列表) ThreadID来自Thread.CurrentThread.ManagedThreadId 以下是我如何启动我的BackgroundWorkers: foreac

我目前正在从事一个多线程项目,涉及几个并行运行的耗时任务

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

  • 当任务必须写入日志文件时,我会将日志写入字典:
    \u logList[id]。添加(消息)
  • 此字典的Key=ThreadID,Value=worker的日志(字符串列表)
  • 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);
}
而FlushWrite仅将threadId的日志列表写入日志文件:

WriteMessageToFile(_logList[id]);
大多数情况下,这是可行的。但有时,我会看到一种奇怪的行为:

  • 多个任务使用相同的ThreadID
  • 当ThreadID X的第一个任务N结束时,它调用RunWorkerCompleted委托,并仅刷新其日志+ThreadID X的下一个任务N+1的一部分(因为任务尚未结束)
  • 当任务N+1真正结束时,它会刷新剩余的日志以进行写入,但是日志文件很乱,因为它不整洁
我知道托管线程id可能会被回收和重用,但我认为发生这种情况的唯一方法是,当运行的BackgroundWorker尚未调用RunWorkerCompleted时,线程已经被重用(新调用
DoWork

我说得对吗?在这种情况下,我有什么不明白的吗

在这种情况下,使用ManagedThreadId作为字典的键可能是一种不好的做法


感谢您的帮助:)

我发现了我的问题:在
FlushWrite
操作期间,执行了锁定。如果工作线程等待的时间过长,则另一个工作线程可能会写入同一个ThreadID,因此在本例中操作的刷新是不一致的

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


代码也已重写,以更改
任务的
BackGroundWorker
。运行
。谢谢:)

事实上,当您[可能]有独特的任务时,为什么要使用ManagedThreadId作为密钥(只是对其唯一性的假设很弱)?为什么不使用MyTask作为字典键?但您仍然可以做得更好,并将记录器传递给gbWorker_doWork。最后,为什么要使用BackgroundWorker?你在开发winforms应用程序吗?我认为使用ManagedThreadId是最简单的关键。事实上,我的任务是独一无二的,所以我可以用它作为关键!你通过记录器是什么意思,那怎么行?最后,我只知道BackgroundWorker的多线程:我不是在开发winform应用程序,你认为我不应该在我的任务中使用这个类吗?你有什么建议吗?:)感谢您不要使用
BackgroundWorker
我建议您使用
任务。如果您需要报告进度,请运行
和异步/等待,并结合
进度。您可以看到这两个选项之间的实际比较。今天,在新开发中使用
BackgroundWorker
s的唯一理由是维护旧版应用程序,这些应用程序运行在过时的.NET Framework版本上。@TheodorZoulias感谢您的回答。我无法更改为Task.Run,但是如果我仍然使用ManagedThreadId作为密钥,您认为它会解决我的日志记录问题吗?或者你的意思是我应该用进度来写日志?对不起,你的问题太复杂了,我无法理解,所以我不能提供任何关于如何解决它的建议。我刚才提到了
任务。Run
和async/await是过时的
BackgroundWorker
的现代替代品。如果无法使用
任务.运行
,则使用
进度
的价值会相应降低。
BackgroundWorker
有自己的进度报告机制,为什么要混合使用呢?
WriteMessageToFile(_logList[id]);