Webworkers and DI questions #20
-
Hi, Thank you for your efforts and your library, it works really great. I'm moving parts of my services to the webworkers, and I have some concerns about the singletons, service registrations, and accidental executions in the web worker context. Could you please share some information on what happens under the hood, so I can be confident about my assumptions and understand how to make my code stable?
Thank you very much for what you do! The library functionality is amazing. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 3 replies
-
Yes. Program.cs is loaded in a WebWorker context just like it does in a Window context. The main difference is caused by the change from Unless you are doing more than setting up DI in your Program.cs it usually does not matter if you register services you will not use. They will not be instantiated if they are not used. Even Singletons are not created until they are used in a component or service that requires them The only services that are started be default in WebWorkers are the WebWorkerService, to listen for requests, and BlazorJSRuntime which is a dependency of WebWorkerService. It is difficult to say what will happen with your custom code in your Program.cs without knowing what your custom code is. If your custom code tries to use localStorage it will fail in a web worker as localStorage is not available there. In your Program.cs you can check if it is running in a Window context or a WebWorker and perform tasks based on that information if desired. Example below. Example context check in a Program.cs var host = builder.Build();
var JS = host.Services.GetRequiredService<BlazorJSRuntime>();
if (JS.IsWindow)
{
Console.WriteLine("Running in a window context");
}
else if (JS.IsDedicatedWorkerGlobalScope)
{
Console.WriteLine("Running in a dedicated worker context");
}
else if (JS.IsSharedWorkerGlobalScope)
{
Console.WriteLine("Running in a shared worker context");
}
await host.BlazorJSRunAsync();
Not at this time. I would be interested in seeing an implementation though. You are welcome to fork the repo and try it out.
I have needed to do this in some projects of mine. I use the method below to only register services in the context needed. builder.Services.AddBlazorJSRuntime();
// Once the above line has been called you can access the static property BlazorJSRuntime.JS which is the property returned when accessing the BlazorJSRuntime service.
var JS = BlazorJSRuntime.JS;
if (JS.IsWindow)
{
Console.WriteLine("Running in a window context");
builder.Services.AddSingleton<SomeServiceOnlyUsedInAWindow>();
}
else if (JS.IsWorker)
{
Console.WriteLine("Running in a dedicated or shared worker context");
builder.Services.AddSingleton<SomeServiceOnlyUsedInAWorker>();
}
GetWebWorker() should not throw an exception. It returns null if WebWorkerService.WebWorkerSupported == false. GetService<T>() should never throw an exception as it is just returning a DispatchProxy wrapped interface that knows how to call that interface on the WebWorker. You can use the properties For a simple fallback when not supported: Example component code that uses a service (IMyService) in a WebWorker if supported and in the default Window context if not. [Inject]
WebWorkerService WebWorkerService { get; set; }
[Inject]
IServiceProvider ServiceProvider { get; set; }
// MyServiceAuto will be IMyService running in the WebWorker context if available and IMyService running in the Window context if not
IMyService MyService { get; set; }
WebWorker? webWorker { get; set; }
protected override async Task OnInitializedAsync()
{
// GetWebWorker() will return null if WebWorkerService.WebWorkerSupported == false
webWorker = await WebWorkerService.GetWebWorker();
MyService = webWorker != null ? webWorker.GetService<IMyService>() : ServiceProvider.GetService<IMyService>();
await base.OnInitializedAsync();
} The best way to learn about how it works is to download the repo, run it, modify it, and look at the code. The entire library is open source. I am here to help if you run into problems or have any more questions. Good luck. 👍 |
Beta Was this translation helpful? Give feedback.
Yes. Program.cs is loaded in a WebWorker context just like it does in a Window context. The main difference is caused by the change from
RunAsync()
call toBlazorJSRunAsync()
. The BlazorJSRunAsync() method checks if it is working in a Window context and only calls RunAsync() if it is running in a Window context. This pr…