I'm developing simple online game using Blazor WASM. Just recently I found that Blazor client is single threaded, which is quite disastrous for most of my algorithms. I want to implement better architecture that authoritative server and enable to run the code on client side as well (for lag compensation and stuff...). The idea of online communication for each frame is as follows:
So on client side there are basically three threads - one for sending actions to server when key is pressed, second for receiving messages from server and third for executing the game code. As you can see, one thread is not enough for me :D
Additional info - online communication is realized by SignalR.
I know that multithreading will be possible in .net 8 (but sadly I can't wait). I tried prerelease but I didn't get it running.
Any help or tips greatly appreciated ;)
Providing code for better understanding.
//Executed 60 per second
private async Task Frame()
{
    //serialization of actions
    json = JsonConvert.SerializeObject(myActions);
    Task.Run(() => hubConnection.SendAsync("ExecuteList", json, id)); //still 
    the same thread
    myActions.Clear();
    ToolsGame.ProceedFrame(gvars, now);
    StateHasChanged();  
}
SignalR listening for messages from server:
hubConnection.On<string>("ExecuteList", (actionMethodNamesJson) =>
{
        ExecuteList(actionMethodNamesJson); //deserialize actions from all clients
        StateHasChanged();
});
SpawnDev.BlazorJS.WebWorkers adds multithreading via Workers and SharedWorkers to Blazor WASM .Net 6, 7 and 8. Just add the Nuget package, modify your Program.cs and then you can call any registered service interface on a Worker or SharedWorker thread.
// Program.cs
// ...
using SpawnDev.BlazorJS;
using SpawnDev.BlazorJS.WebWorkers;
    
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
// Add SpawnDev.BlazorJS.BlazorJSRuntime
builder.Services.AddBlazorJSRuntime();
// Add SpawnDev.BlazorJS.WebWorkers.WebWorkerService
builder.Services.AddWebWorkerService();
// Add services that will be called on the main thread and/or worker threads (Worker services must use interfaces)
builder.Services.AddSingleton<IMathsService, MathsService>();
// build and Init using BlazorJSRunAsync (instead of RunAsync)
await builder.Build().BlazorJSRunAsync();
To use it:
[Inject]
WebWorkerService workerService { get; set; }
// Get a new WebWorker
var webWorker = await workerService.GetWebWorker();
// Get WebWorker service proxy
var workerMathService = webWorker.GetService<IMathsService>();
// Call async methods on your worker service thread
var result = await workerMathService.CalculatePi(piDecimalPlaces);
Documentation and examples are on GitHub. I am quick to help with any problems, just file an issue on the repo.
GitHub repo: https://github.com/LostBeard/SpawnDev.BlazorJS
Nuget page: https://www.nuget.org/packages/SpawnDev.BlazorJS.WebWorkers
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With