protoken
protoken

Reputation: 339

Calling async function with `function().Wait()` works, but `async function()` crashes

I'm calling a 3rd party library from my C# code, and have found that ctx.CreateSiteAsync(communicationSiteInfo).Wait(); works well, while await ctx.CreateSiteAsync(communicationSiteInfo); causes the application to crash. As .Wait() to the best of my knowledge causes the thread to block, I'm interested inn getting the await approach to work. Here an extract from my code to put the above calls in context:

        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....

If I'm not mistaking, the function I'm calling it this one: ClientContextExtensions.cs. I'm pretty new to C#, so perhaps the reason for the application crashing is obvious, but I can't see why the await wouldn't work, as the function I'm calling has async Task in it's definition.

EDIT: The weird thing regarding the exception is that the application simply crashes, and the catch clause is never reached. I don't know, but maybe this has something to do with threading or context or something in that the exception thrown in the async function call are not returned to the current thread. The application crashes on the await ctx.CreateSiteAsync(communicationSiteInfo); call.

EDIT 2: It looks as though I can simplify the issue at hand, but using this as an example instead:

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

            }

This causes the code to crash on await Task.Delay(1000).ConfigureAwait(false);. If is instead use Task.Delay(1000).Wait(), the code works as expected.

Upvotes: 0

Views: 1168

Answers (2)

Gabriel Luci
Gabriel Luci

Reputation: 41008

I see your answer, but I don't think that's the root cause. It's perfectly fine to use static async Task Main(), as long as your project is using C# 7.0 or higher (when that was introduced). If changing that (and making everything else synchronous, as you'd have to after removing async) made the symptom go away, then that means that somewhere along your call stack, you were missing an await.

For example, this works just fine:

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

But if you remove the await in Main, then the application would end before "Done pausing" is printed. This is because async methods run synchronously at first, but return at the first await that acts on an incomplete Task. (Pause() returns a Task when it hits await Task.Delay(1000) - before the waiting is completed)

So if you don't await an async method, then your code will just move on to the next line before the work is done. Sometimes you actually want this, but often not.

Since it otherwise runs synchronously, replacing the await with .Wait() would halt the thread and the method would not return, making it suddenly "work".

In your code, that means that either you weren't awaiting createSite() or weren't awaiting whatever called the method that called createSite(), etc.

Microsoft has a series of very well-written articles about asynchronous articles that are worth reading. Start here: Asynchronous programming with async and await

Upvotes: 1

protoken
protoken

Reputation: 339

Thanks for the comments on my initial post. I got it working now, and believe it's because of I defined the Main method to be async, like this: static async Task Main().

Upvotes: 0

Related Questions