Home > Back-end >  Blazor-Wasm: Why does `await Task` blocks UI, but `await`-`async` doesn't?
Blazor-Wasm: Why does `await Task` blocks UI, but `await`-`async` doesn't?

Time:03-30

I'm currently trying to call asynchronously an expensive method in blazor WASM while not blocking the UI thread.

According to answers to this question, it is impossible. However, these date back to a couple of years ago, and according to the WebAssembly roadmap, threading is supported by modern browsers.

Also, I can await function calls without blocking the UI thread, as long as the functions are awaitable from the bottom up.

In the following code snippet, clicking the Foo button will cause the UI to hang for a couple of seconds while the operation is carried out, but clicking the Bar button will process a similar (but awaitable) operation in the background while keeping the UI responsive.

If WebAssembly doesn't support multi-threading, why does the second option seem to work with multiple threads? If it does support multi-threading, why does the first option block the UI?

@page "/asynctest"

<div >
    <div >
        @DisplayValue
    </div>
    <div >
        <button type="button" @onclick="OnClickFoo">Foo</button>
    </div> 
    <div >
        <button type="button" @onclick="OnClickBar">Bar</button>
    </div> 
</div>

@code{
    private string DisplayValue = "";
    private double Result;
    private async Task OnClickFoo(EventArgs e)
    {
        DisplayValue = "Working...";
        Result = await Task.Run(() => Frobnicate()); // Blocks UI thread
        DisplayValue = Result.ToString();
    }
    private async Task OnClickBar(EventArgs e)
    {
        DisplayValue = "Working...";
        Result = await FrobnicateAsync(); // Doesn't block UI thread
        DisplayValue = Result.ToString();
    }
    private int Frobnicate()
    {
        Thread.Sleep(2000); // do some heavy work
        return 42;
    }
    private async Task<int> FrobnicateAsync()
    {
        await Task.Delay(2000); // do some heavy work async
        return 42;
    }
}

CodePudding user response:

As far as I am aware, Blazor WASM does not support multithreading, you only get 1 thread.

In the "OnClickBar" method, you are not creating a different thread. You are using the async/await state machine which returns control to the calling thread. The Task.Delay(2000) does not block the thread as seen in this Stack Overflow question

In the "OnClickFoo" method, you are calling Task.Run which does try to create a background thread - this does not work properly in WASM as you have a single thread, so when you call Thread.Sleep(2000); - it is the UI thread that is sleeping.

More info on threading here: Microsoft Docs - Threads

Related Stack Overflow question

  • Related