c# - 使用当前同步上下文的并行 ForEach

标签 c# wpf multithreading

我对 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 线程。由于新线程正在使用当前同步上下文,这不就是在主线程上按顺序执行所有这些任务吗?如果是这样,这样做有什么值(value)吗?

最佳答案

  1. List<Task>不是线程安全的,你不能在 Parallel.ForEach 中使用它没有锁定(即使您预先确定了列表的大小,它仍然不安全)。
  2. 如果您所做的只是使用 TaskFactory 启动一个新线程,则没有理由并行执行此操作。调用 StartNew 的速度非常快,因此没有必要。
  3. Parallel类使用调用线程作为工作线程之一,因此可以在 Parallel.ForEach 中使用调用线程
  4. 你调用 TaskScheduler.FromCurrentSynchronizationContext()如果从设置了 SynchronizationContext 的线程调用,这可能是 UI 线程或后台线程 SynchronizationContext.SetSynchronizationContext(调用,将导致使用该调度程序启动的任务从 UI 线程运行。

发布的代码唯一能给您的(如果您解决了问题 1,那么它就不再有错误)是您将工作排到消息队列的末尾进行处理。如果您想将工作推迟到以后使用 Dispatcher.BeginInvoke ,这可能很有用。是一种更好的方法。

关于c# - 使用当前同步上下文的并行 ForEach,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43355959/

相关文章:

java - 如何避免线程中出现 HeadlessException?

c# - Grouped TreeView 中的 WPF ListView 不起作用

c# - 看不到无限循环

c# - 推荐程序结构

c# - 使用 WCF Duplex 回调更新 JQuery 进度条?

c# - 使用@Url.Action 生成 URL

c# - 哪个日志实用程序适用于 C# 中的 .NET 应用程序(ASP.NET、WinForms)?

c# - ObservableCollection 未绑定(bind)到组合框

c# - TextBlock 未显示在 ListView 中

Python 线程/线程实现