线程池,多线程,异步等。我应该使用什么?

时间:2013-10-07 19:21:27

标签: c# multithreading

我的情景:

  • 我有一个应用程序,人们将项目ID列表输入。
  • 对每个项目运行Web服务上的操作
  • DataGridView绑定到某些类的BindingList / ObservableCollection并在每次操作完成后更新
  • 可能还有一个状态标签,通知用户已完成的项目数。
  • 输入列表实际上可以是任何大小,但可能会限制在500左右。

我应该采用什么解决方案?线程池?根据需要创建/销毁线程?我编写了大部分代码,但需要搜索/更新不在UI线程上。哪里是一个好的起点?

编辑:我必须使用.NET 3.5,不能使用像async / await这样的东西:(

1 个答案:

答案 0 :(得分:3)

一般来说,这听起来像基于语言的async / await关键字可能是最佳选择,原因有两个:

  
      
  • 对每个项目运行Web服务上的操作
  •   

鉴于这是一个Web服务调用,它将自然而然地是IO绑定和异步的。使用TPL或其他例程(无需小心)可能会降低整体吞吐量。通常,您希望这些操作保持异步,并且如果您从一开始就按照这种方式处理它们,那么它将扩展得最好。

  
      
  • DataGridView绑定到某些类的BindingList / ObservableCollection并在每次操作完成后更新
  •   
  • 可能还有一个状态标签,通知用户已完成的项目数。
  •   

鉴于您将UI控件绑定到结果,async / await支持将调用映射回调用同步上下文将简化将结果添加到集合中。这将使代码在最终状态下保持非常简单。

请注意,您可能希望存储异步操作返回的Task<T>,然后等待返回的值(不只是直接等待消息调用)。这将允许您同时触发对服务的多个请求。例如,您的代码可能看起来像(*没有异常处理等):

// Start each operation, and store in a list

var asyncOperations = ids.Select(id => FetchDataFromWebServiceAsync(id)).ToList();

while (asyncOperations.Any())
{
    // When one operation completes, remove it from the list of ops running
    var completed = await Task.WhenAny(asyncOperations);
    asyncOperations.Remove(completed);

    // Grab the result and use
    YourResultType finished = completed.Result;
    // Add to UI, update progress, etc...
}