为什么两个函数都不并行执行

时间:2018-10-12 01:56:47

标签: c#

我有一个问题,如果我运行Main方法,并在其中调用(GetRankedEditorsPickList),它将异步运行,但如果运行(GetRankedEditorsPickList1),则将按顺序运行。您可以查看托管的threadId和结果。

有人可以告诉我为什么吗?这是linqpad代码。

async Task Main()
    {
        List<string> y = new List<string>() { "a","b","c" };
                    var rankedFeedBatchTasks = y.Select(async (batch, index) =>
                    {
                        return new
                        {
                            Index = index,
                            RankedList = await GetRankedEditorsPickList1(batch).ConfigureAwait(false)
                        };
                    }).ToList();
         var rankedFeedBatches = await Task.WhenAll(rankedFeedBatchTasks);
         "Completed".Dump();
    }

    async Task<string> GetRankedEditorsPickList(string batch)
    {   
         $"Started + {Environment.CurrentManagedThreadId}".Dump();
         await Task.Delay(TimeSpan.FromSeconds(5));
         batch = batch + "1";   
         $"Ended + {Environment.CurrentManagedThreadId}".Dump();
        return batch;
    }

    // Define other methods and classes here
    Task<string> GetRankedEditorsPickList1(string batch)
    {
        $"Started + {Environment.CurrentManagedThreadId}".Dump();
        Thread.Sleep(TimeSpan.FromSeconds(5));
        batch = batch + "1";
        $"Ended + {Environment.CurrentManagedThreadId}".Dump();
        return Task.FromResult(batch);
    }

第一个方法调用结果::

Started + 11
Started + 11
Started + 11
Ended + 10
Ended + 13
Ended + 14
Completed

第二种方法调用结果::

Started + 11
Ended + 11
Started + 11
Ended + 11
Started + 11
Ended + 11

已完成

3 个答案:

答案 0 :(得分:3)

GetRankedEditorsPickList是异步函数,而GetRankedEditorsPickList1不是异步函数。这就是为什么后者顺序运行的原因。

更具体地说:

  • Task.Delay不同,Thread.Sleep不是异步的。
  • Task.FromResult也不是异步的。它只是根据已经计算出的结果创建一个已经完成的任务。在这种情况下,是同步计算的。换句话说,它为您的方法提供了一个签名,就像实际上是一个异步函数一样。

答案 1 :(得分:1)

建议您阅读 Stephen Cleary的“ C#烹饪书中的并发性” ,在本书中给出了解释和使用Task.FromResult的方式

  

问题   您需要使用异步签名来实现同步方法。这个   如果您从异步接口或基类继承,则会出现这种情况   但希望同步实施。当单位   当需要简单的存根或模拟异步时,测试异步代码   界面。

     

解决方案   您可以使用Task.FromResult创建并返回一个已经完成的新Task   具有指定值

     

Task.FromResult(batch)返回已完成的任务,这就是为什么GetRankedEditorsPickList1被同步执行

答案 2 :(得分:0)

异步并不意味着并行。异步用于克服顺序执行(即,如果您不希望以顺序方式执行某些任务,则可以使用异步)