繁体   English   中英

为什么不等待异步就被告知

[英]Why do async await without being told

我试图使我的系统的一部分并行运行,但是出于某些原因,即使我没有告诉它等待,它也会在每个元素开始下一个之前等待每个元素。 我想开始为每个this.Items执行ExecuteItem ,然后在它们全部完成后继续执行。

bool singleThread = false;
public async Task Execute()
{
        if (!this.singleThread)
        {
            var tasks = this.Items.Select(x => this.ExecuteItem(x)).ToArray();
            Task.WaitAll(tasks);
        }
        else
        {
            foreach (var item in this.Items)
            {
                await this.ExecuteItem(item);
            }
        }
}

private async Task ExecuteItem(IMyItem item)
{
        MappedDiagnosticsContext.Set("itemRef", item.ItemRef);
    try
    {
        await this.HandelItem(item);
    }
    catch (Exception exp)
    {
        Logger.ErrorException(string.Format("Execution for {0} failed.", item.ItemName), exp);
        Logger.Error("Error Message: ", exp.Message);
    }

    MappedDiagnosticsContext.Remove("itemRef");
}

为了明确我的问题,我的代码的行为就像写了以下内容

var tasks = this.Items.Select(x => await this.ExecuteItem(x)).ToArray();

为了确保这不是某种linq问题,我将问题代码tasks[i] = this.ExecuteItem(this.Items[i]);为以下代码,但是代码仍然阻止tasks[i] = this.ExecuteItem(this.Items[i]);

        Task[] tasks = new Task[this.Items.Count];
        for (int i = 0; i < this.Items.Count; i++)
        {
            Console.WriteLine("Adding " + this.Items[i].ItemName);
            tasks[i] = this.ExecuteItem(this.Items[i]);
        }
        Console.WriteLine("Waiting!!!");
        Task.WaitAll(tasks);

HandelItem某些内容HandelItem

async方法不会完全异步运行,它们会同步执行直到达到await为止。 因此,所有ExecuteItem ,直到HandelItem都将在构建tasks列表之前运行。 如果它是一个async方法,则此同步行为将继续到HandelItem ,因此HandelItem可能在构建任务列表时正在执行。

通过以下示例程序可以轻松看出这一点:

static void Main(string[] args)
{
  var items = Enumerable.Range(1, 2);
  Console.WriteLine("Start");
  var tasks = items.Select(i => AsyncMethod(i)).ToArray();
  Console.WriteLine("Got tasks");
  Task.WaitAll(tasks);
  Console.WriteLine("Done!");
}

static async Task AsyncMethod(int i)
{
  Console.WriteLine("Enter {0}", i);
  await AsyncMethod2(i);
  await Task.Delay(1000);
  Console.WriteLine("Exit {0}", i);
}

static async Task AsyncMethod2(int i)
{
  Console.WriteLine("Enter2 {0}", i);
  await Task.Delay(2000);
  Console.WriteLine("Exit2 {0}", i);
}

它的输出是:

Start
Enter 1
Enter2 1
Enter 2
Enter2 2
Got tasks
Exit2 2
Exit2 1
Exit 1
Exit 2
Done!

因此,这两种async方法都在构建任务列表时运行,直到必须等待为止。 因此,如果HandelItem执行非异步操作,则会导致阻塞。

如果您希望任务并行执行; 然后等待所有步骤完成:

await Task.WhenAll(this.Items.Select(item=>this.ExecuteItem(item)));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM