SteveSandersonMS / WebWindow

.NET Core library to open native OS windows containing web UI on Windows, Mac, and Linux. Experimental.
Apache License 2.0
1.99k stars 215 forks source link

Race condition in ComponentsDesktop.cs intermittently prevents web window from opening correctly #90

Closed budcribar closed 2 years ago

budcribar commented 4 years ago

@SteveSandersonMS I found a race condition and isolated it to line 65 of ComponentsDesktop.cs. If you insert a Thread.Sleep(2000) you will see it consistently as the task on line 60 does not get through enough initialization before the code on line 76 WebWindow.NavigateToUrl(BlazorAppScheme + "://app/"); gets executed.

i.e. Task.Factory.StartNew(async () => { try { var ipc = new IPC(WebWindow);

                Thread.Sleep(2000);
                await RunAsync<TStartup>(ipc, appLifetimeCts.Token, completed);

            }
            catch (Exception ex)
            {
                UnhandledException(ex);
                throw;
            }
        });

will prevent the web window from initializing correctly.

This seems to fix the problem. But further investigation is needed . . . var completed = new ManualResetEventSlim();

        CancellationTokenSource appLifetimeCts = new CancellationTokenSource();

        Task.Factory.StartNew(async () =>
        {
            try
            {
                var ipc = new IPC(WebWindow);

                Thread.Sleep(2000);
                await RunAsync<TStartup>(ipc, appLifetimeCts.Token, completed);

            }
            catch (Exception ex)
            {
                UnhandledException(ex);
                throw;
            }
        });

        try
        {
            completed.Wait();
            WebWindow.NavigateToUrl(BlazorAppScheme + "://app/");

            WebWindow.WaitForExit();
        }
        finally
        {
            appLifetimeCts.Cancel();
        }
    }

.....

private static async Task RunAsync(IPC ipc, CancellationToken appLifetime, ManualResetEventSlim completed) {

        var configurationBuilder = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json", optional: true);

        DesktopJSRuntime = new DesktopJSRuntime(ipc);
        completed.Set();
        await PerformHandshakeAsync(ipc);

The ManualResetEventSlim will prevent the WebWindow.NavigateToUrl from running until DesktopJSRuntime has been initialized. This seems to fix the problem but I'm not sure if there are other issues or not with the race between NavigateToUrl and RunAsync.