简体   繁体   中英

Exception when using await on async function

I'm trying to use LinqToTwitter to post newsarticles to Twitter from an ASP.NET CMS. I've created a static class that will handle it for me as the outcome will be logged anyway and won't affect the rest of the website. However, when I try to run it and post to Twitter, an exception occurs:

System.InvalidOperationException: An asynchronous module or handler completed while an asynchronous operation was still pending

The full class:

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

The weird part (for me at least) is that I use the function as described in the tooltip and documentation of LinqToTwitter. I get that some function is completed while another was still running but isn't that what the "await" keyword is for?

I tried cutting out the PostTwitter function or the code after the point of failure but still the same result. I've searched a lot for a solution but I might just be terrible at searching or searching in the wrong direction. I even registered on SO just to ask this question! :D

The culprit here is the fact that you're invoking Post with an async void method:

internal static async void PostTwitter

Async void functions exists solely for event handling, and have very odd and unpredictable error handling when used outside of this context. See this MSDN article for information.

Switch your async void method to an async Task method and some actual errors may start to bubble to the surface:

internal static async Task PostTwitter

Stephen Cleary actually goes into this problem in great detail in another SO post. To quote from him directly regarding the behavior of asynchronous methods:

Historically, ASP.NET has supported clean asynchronous operations since .NET 2.0 via the Event-based Asynchronous Pattern (EAP), in which asynchronous components notify the SynchronizationContext of their starting and completing

Whenever your code calls into SocialTwitter.PostTwitter, the PostTwitter method notifies the SynchronizationContext that it's started, bypassing whichever framework you're using completely and going straight to the ASP.NET core. The PostTwitter method than starts the async Post method, which also notifies the SynchronizationContext that it has started.

The ASP.NET frameworks understand how to wait for Tasks, but, excluding WinForms and WebForms in very specific situations, know little about how to handle async void methods. Thus the framework believes the async void to be complete and it attempts to notify the SychronizationContext that the async void method has finished, even though the async void method spawned an async Task method that's still running. As part of a series of safety nets designed specifically to catch errors like this, the SynchronizationContext throws the InvalidOperationException that you've been seeing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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