使用 'function() 调用异步函数.Wait()' 工作,但 'async function()' 崩溃



我正在从我的 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(),代码按预期工作。

我看到了你的答案,但我认为这不是根本原因。使用static async Task Main()是完全可以的,只要你的项目使用的是C#7.0或更高版本(引入时(。如果更改它(并使其他所有内容同步,就像删除async后必须做的那样(使症状消失,那么这意味着在您的调用堆栈中的某个地方,您错过了一个await

例如,这工作得很好:

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");
}
}

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

因此,如果您没有awaitasync方法,那么您的代码将在工作完成之前移动到下一行。有时你真的想要这个,但往往不是。

由于它以其他方式同步运行,因此用.Wait()替换await将停止线程并且该方法不会返回,使其突然"工作"。

在你的代码中,这意味着要么你没有等待createSite()要么没有等待调用createSite()的方法,等等。

Microsoft有一系列关于异步文章的写得很好的文章,值得一读。从这里开始:异步和等待的异步编程

感谢您对我最初帖子的评论。我现在让它工作了,并相信这是因为我将Main方法定义为异步的,如下所示:static async Task Main().

最新更新