【问题标题】:Exception when using await on async function在异步函数上使用 await 时出现异常
【发布时间】:2015-06-28 13:11:55
【问题描述】:

我正在尝试使用 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 的工具提示和文档中描述的函数。我知道 some 功能已完成,而另一个仍在运行,但这不是“await”关键字的用途吗?

我尝试在故障点后删除 PostTwitter 函数或代码,但结果仍然相同。我已经搜索了很多解决方案,但我可能只是在搜索或搜索错误的方向时很糟糕。我什至在 SO 上注册只是为了问这个问题! :D

【问题讨论】:

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


    【解决方案1】:

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

    internal static async void PostTwitter
    

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

    将您的 async void 方法切换为 async Task 方法,一些实际错误可能开始浮出水面:

    internal static async Task PostTwitter
    

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

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

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

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

    【讨论】:

    • 很高兴我能帮上忙!我自己曾经与那个例外作斗争
    猜你喜欢
    • 1970-01-01
    • 2017-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-04
    • 2019-11-27
    相关资源
    最近更新 更多