我是否真的在这里使用任务和异步获得任何东西

时间:2013-07-30 15:20:44

标签: c# task-parallel-library async-await

我正试图掌握Tasks和Async Await关键字。我有一个基本上调用 n 方法的示例方法。需要注意的两个要点是

  • 我不关心方法在
  • 中运行的顺序
  • 应在后台线程上调用所有方法

这是代码。

public async void Handle<T>(T entry) {
    await Task.Run(() => {
        Parallel.ForEach(_handlers, pair => {
            pair.Value.Invoke(_reference, new object[] {
                entry
            });
        });
    });

我的问题是我实际上从上面的代码中获得了任何异步或并行性吗?

2 个答案:

答案 0 :(得分:5)

我假设您在UI应用程序中运行,因为服务器上的并行代码非常少见。

在这种情况下,在Task.Run中包装并行代码是完全正常的,并且当您希望异步执行并行代码时,这是一种常见的模式。

我会做一些改变:

  1. 避免使用async void。返回Task,这样您就可以更干净地处理错误。
  2. 遵循基于任务的异步模式命名约定(即, 使用Async)结束您的方法。
  3. 直接返回Task而不是async / await(如果您的整个async方法只是await任务,则可以避免一些开销只需直接返回任务。)
  4. 像这样:

    public Task HandleAsync<T>(T entry) {
        return Task.Run(() => {
            Parallel.ForEach(_handlers, pair => {
                pair.Value.Invoke(_reference, new object[] {
                    entry
                });
            });
        });
    

    我还会考虑另外两种可能性:

    1. 考虑使用Parallel.Invoke代替Parallel.ForEach。在我看来,Parallel.Invoke与您实际尝试的内容更为匹配。(请参阅下面的svick评论)。
    2. 考虑将并行代码保留为同步方法(例如public void Handle<T>(T entry)),使用Task.Run 调用(例如await Task.Run(() => Handle(entry));)。如果您的Handle[Async]方法旨在成为通用库的一部分,那么您希望避免在异步方法中使用Task.Run

答案 1 :(得分:1)

不,你在这里什么都没有。即使你让它返回Task(以便调用者可以检查所有内容何时完成),如果没有异步,你会更好:

public Task Handle<T>(T entry)
{
    return Task.Run(() =>
    {
        Parallel.ForEach(_handlers, pair => 
        {
            pair.Value.Invoke(_reference, new object[] { entry });
        });
    });
}