Aspnetcore: Does Blazor WebAssembly support multi threading?

Created on 23 Sep 2019  路  2Comments  路  Source: dotnet/aspnetcore

While reading the below post, this doubt came to my mind.

https://visualstudiomagazine.com/articles/2019/09/18/blazor-webassembly.aspx

Blazor WebAssembly is described by Microsoft thusly:
The principal hosting model for Blazor is running client-side in the browser on WebAssembly. The Blazor app, its dependencies, and the .NET runtime are downloaded to the browser. The app is executed directly on the browser UI thread. UI updates and event handling occur within the same process. The app's assets are deployed as static files to a web server or service capable of serving static content to clients.

The above bold line says that Blazor App will reside in the browser UI thread and all updates are handled within the same process. So I have the below questions regarding this.

  • Does Blazor WebAssembly run in single thread like JavaScript?
  • How to handle long running process or large data operations in Blazor WebAssembly?

I might have misunderstood the above statement, I appreciate if someone correct me if i am wrong.

Docs area-blazor

Most helpful comment

Thanks for contacting us @Madhust.

Blazor currently is single threaded and executes everything on the "UI thread". The general guidance for long running jobs is:

  • On the server-side, execute compute intensive tasks in a background thread and marshall the results back to the UI thread through the use of ComponentBase.Invoke.
  • On the client-side there are no background threads but you can probably achieve a similar thing by breaking the compute intensive work into multiple pieces and using Task.Yield to let the UI thead perform other work between executions.

    • For example if you are processing 1000.000 items you can write a foreach loop and yield every 100 items.

  • For long running asynchronous requests you can keep track of the initial request and perform updates by calling StateHasChanged().

    • For example if you are doing 100 network requests you can simply call state has changed after each one of them.

The most important thing to remember is to never call .Result or .Wait() as that will create a deadlock in your application as when async work tries to return to the UI thread, it won't be able to due to the fact that it is blocked in the .Result or .Wait() task.

If you need to check on the results of a task you can keep a reference to it on a field in the component or do some work as a continuation for the task.

Hope this helps.

@danroth27 Do you have your long running async sample? That should go in the docs. This guidance too, once we've reviewed it more thoroughly.

All 2 comments

If you are calling out to servers etc then those calls will be async. If you have a long-running in-process task then you can yield execution cycles like this...

@page "/"

<input/>
<button @onclick=DoLongRunningTask>Do long running task</button>

@code {
    async Task DoLongRunningTask()
    {
        System.Diagnostics.Debug.WriteLine("Starting long running task");
        DateTime endTime = DateTime.UtcNow.AddSeconds(10);
        while (DateTime.UtcNow < endTime)
        {
            await Task.Delay(100);
        }
        System.Diagnostics.Debug.WriteLine("Finished long running task");
    }
}

Thanks for contacting us @Madhust.

Blazor currently is single threaded and executes everything on the "UI thread". The general guidance for long running jobs is:

  • On the server-side, execute compute intensive tasks in a background thread and marshall the results back to the UI thread through the use of ComponentBase.Invoke.
  • On the client-side there are no background threads but you can probably achieve a similar thing by breaking the compute intensive work into multiple pieces and using Task.Yield to let the UI thead perform other work between executions.

    • For example if you are processing 1000.000 items you can write a foreach loop and yield every 100 items.

  • For long running asynchronous requests you can keep track of the initial request and perform updates by calling StateHasChanged().

    • For example if you are doing 100 network requests you can simply call state has changed after each one of them.

The most important thing to remember is to never call .Result or .Wait() as that will create a deadlock in your application as when async work tries to return to the UI thread, it won't be able to due to the fact that it is blocked in the .Result or .Wait() task.

If you need to check on the results of a task you can keep a reference to it on a field in the component or do some work as a continuation for the task.

Hope this helps.

@danroth27 Do you have your long running async sample? That should go in the docs. This guidance too, once we've reviewed it more thoroughly.

Was this page helpful?
0 / 5 - 0 ratings