我对C#中的线程有点新,但我继承了一个相当多的代码库。我正在看一些似乎在逻辑上按顺序运行的多线程代码段。这是一个例子:
// Draw the nodes.
var factory = new TaskFactory(TaskScheduler.FromCurrentSynchronizationContext());
var drawingTasks = new List<Task>(nodePoints.Count);
Parallel.ForEach(nodePoints, nodePoint =>
{
Task task = factory.StartNew(() => DrawNode(token, nodePoint, groupList), token, TaskCreationOptions.None, factory.Scheduler);
if (task != null)
drawingTasks.Add(task);
});
await factory.ContinueWhenAll(drawingTasks.ToArray(), result =>
{
_event.Publish(new MapNodesDrawnEvent());
});
调试应用程序显示这是在主线程上执行的,我假设它也是UI线程。由于新线程正在使用当前同步上下文,这不仅仅是在主线程上顺序执行所有这些任务吗?如果是这样,这样做有什么价值吗?
答案 0 :(得分:3)
List<Task>
不是线程安全的,你不能在没有锁定的Parallel.ForEach
内使用它(即使你预先确定了列表的大小,它仍然是不安全的。)Parallel
类使用调用线程作为工作线程之一,因此调用线程可以在Parallel.ForEach中使用TaskScheduler.FromCurrentSynchronizationContext()
如果从设置了SynchronizationContext的线程调用,则可能是UI线程或调用了SynchronizationContext.SetSynchronizationContext(
的后台线程,将导致使用该调度程序启动的任务从UI线程运行。发布的代码给你的唯一的东西(如果你修复了问题1所以它不再是bug)将是你将工作排队到要处理的消息队列的末尾。如果您希望将工作推迟到以后,这可能很有用,但使用Dispatcher.BeginInvoke
是一种更好的方法。