在async函数上使用await时出现异常

时间:2015-04-21 11:36:15

标签: c# asp.net asynchronous linq-to-twitter

我正在尝试使用LinqToTwitter从ASP.NET CMS向Twitter发布新闻文章。我已经创建了一个静态类,它将为我处理它,因为结果将被记录,并且不会影响网站的其余部分。但是,当我尝试运行它并发布到Twitter时,会发生异常:

  

System.InvalidOperationException:在异步操作仍处于挂起状态时完成异步模块或处理程序

全班:

public static class SocialTwitter
{
    internal async static void PostTwitter(string message)
    {
        await Post(message);
    }

    private async static Task Post(string message)
    {
        var auth = new SingleUserAuthorizer
        {
            CredentialStore = new SingleUserInMemoryCredentialStore
            {
                ConsumerKey = ConfigurationManager.AppSettings["TwitterConsumerKey"],
                ConsumerSecret = ConfigurationManager.AppSettings["TwitterConsumerSecret"],
                AccessToken = ConfigurationManager.AppSettings["TwitterToken"],
                AccessTokenSecret = ConfigurationManager.AppSettings["TwitterTokenSecret"]
            }
        };
        await auth.AuthorizeAsync();
        TwitterContext t = new TwitterContext(auth);
        //Exception occurs here
        Status tweet = await t.TweetAsync(Uri.EscapeDataString(message));

        if (tweet != null)
        {
            Util.Log.Info(string.Format("Status posted: ({0}) {1}, {2}", tweet.StatusID, tweet.User.Name, tweet.Text));
        }
        else
        {
            Util.Log.Info("Error occurred posting status to Twitter");
        }
    }
}

奇怪的部分(至少对我来说)是我使用LinqToTwitter的工具提示和文档中描述的功能。我得到某些函数已完成,而另一个函数仍在运行,但这不是“await”关键字的用途吗?

我尝试在故障点之后切断PostTwitter功能或代码,但结果仍然相同。我已经搜索了很多解决方案,但我可能只是在搜索或搜索错误的方向时很糟糕。我甚至在SO上注册只是为了提出这个问题! :d

1 个答案:

答案 0 :(得分:3)

这里的罪魁祸首是您使用异步void方法调用Post:

internal static async void PostTwitter

Async void函数仅用于事件处理,并且在此上下文之外使用时具有非常奇怪和不可预测的错误处理。有关信息,请参阅此MSDN文章。

将async void方法切换为异步任务方法,并且一些实际错误可能会开始冒泡到表面:

internal static async Task PostTwitter

Stephen Cleary实际上在另一篇SO帖子中详细讨论了这个问题。直接引用他关于异步方法的行为:

  

从历史上看,ASP.NET通过基于事件的异步模式(EAP)支持自.NET 2.0以来的干净异步操作,其中异步组件通知SynchronizationContext它们的开始和完成

每当您的代码调用SocialTwitter.PostTwitter时,PostTwitter方法会通知SynchronizationContext它已启动,绕过您完全使用的任何框架并直接进入ASP.NET核心。 PostTwitter方法比启动异步Post方法,该方法还通知SynchronizationContext它已经启动。

ASP.NET框架了解如何等待Tasks,但是,在非常特定的情况下排除WinForms和WebForms,对如何处理异步void方法知之甚少。因此,框架认为async void是完整的,并且它尝试通知SychronizationContext async void方法已完成,即使async void方法产生了仍在运行的异步Task方法。作为专门用于捕获此类错误的一系列安全网的一部分,SynchronizationContext会抛出您已经看到的InvalidOperationException。