用function()。Wait()调用异步函数有效,但是async function()崩溃

时间:2019-11-29 16:43:45

标签: c# .net async-await

我正在从我的C#代码中调用第三方库,并且发现ctx.CreateSiteAsync(communicationSiteInfo).Wait();运行良好,而await ctx.CreateSiteAsync(communicationSiteInfo);导致应用程序崩溃。据我所知,.Wait()会导致线程阻塞,因此我很想让await方法起作用。 这是我的代码的一部分,将上述调用置于上下文中:

        public async Task createSite(string base_url, SiteConfig siteConfig) {
           using(var ctx = new OfficeDevPnP.Core.AuthenticationManager().GetAppOnlyAuthenticatedContext(base_url, this.applicationId, this.applicationSecret)) {
           ctx.Load(ctx.Web, p => p.Title);
           ctx.ExecuteQuery();

           CommunicationSiteCollectionCreationInformation communicationSiteInfo = new CommunicationSiteCollectionCreationInformation {
              Title = siteConfig.title,
              Url = siteConfig.url,
              SiteDesign = siteConfig.siteDesign,
              Description = siteConfig.description,
              Owner = siteConfig.ownerEmailAddress
           };

          try {
           // This works: ctx.CreateSiteAsync(communicationSiteInfo).Wait();
           await ctx.CreateSiteAsync(communicationSiteInfo);

          } catch....

如果我没有记错的话,我称之为“ ClientContextExtensions.cs”的函数。 我是C#的新手,所以也许应用程序崩溃的原因很明显,但是我看不到为什么await无法正常工作,因为我正在调用的函数具有async Task在它的定义中。

编辑:关于异常的奇怪的事情是应用程序只是崩溃了,并且从未到达catch子句。我不知道,但是也许这与线程或上下文有关,或者异步函数调用中抛出的异常不会返回到当前线程。应用程序在await ctx.CreateSiteAsync(communicationSiteInfo);调用时崩溃。

编辑2:看来我可以简化当前的问题,但是以它为例:

 public async Task StartMessageQueuePollAsync()
    {
        while (true)
        {
           await Task.Delay(1000).ConfigureAwait(false); 

            }

这会导致代码在await Task.Delay(1000).ConfigureAwait(false);上崩溃。如果改为使用Task.Delay(1000).Wait(),则代码将按预期工作。

2 个答案:

答案 0 :(得分:0)

感谢您对我的第一篇文章的评论。我现在开始使用它了,并相信是因为我将Main方法定义为异步方法,如下所示: static async Task Main()

答案 1 :(得分:0)

我看到了您的答案,但我认为这不是根本原因。只要您的项目使用的是C#7.0或更高版本(引入该版本),就可以使用static async Task Main()很好。如果进行更改(使所有其他内容保持同步,就像在删除async之后所做的那样)使症状消失了,那么这意味着在调用堆栈的某个地方,您缺少了await

例如,this可以正常工作:

using System;
using System.Threading.Tasks;

public class Program
{
    public static async Task Main()
    {
        Console.WriteLine("Hello.");
        await Pause();
        Console.WriteLine("All done");
    }

    public static async Task Pause() {
        await Task.Delay(1000);
        Console.WriteLine("Done pausing");
    }
}

但是,如果您删除await中的Main,则该应用程序将在打印“完成暂停”之前结束。这是因为async方法最初是同步运行的,但是对不完整的await起作用的第一个Task则是 return 。 (Pause()在到达Task-之前等待完成时返回await Task.Delay(1000)

因此,如果您没有await async方法,那么您的代码将在完成工作之前移至下一行。有时您确实想要这个,但通常不需要。

由于它否则会同步运行,因此用await替换.Wait()会暂停线程并且该方法不会返回,从而使其突然“起作用”。

在您的代码中,这意味着您不是在等待createSite(),就是在等待名为createSite()的方法之类的东西,等等。

Microsoft有一系列关于异步文章的写得很好的文章,值得一读。从这里开始:Asynchronous programming with async and await