代码之家  ›  专栏  ›  技术社区  ›  Ender KARADAG

blazor webassembly多线程模式更新ui问题

  •  0
  • Ender KARADAG  · 技术社区  · 2 年前

    我测试了blazor webassembly,以便与.net8(和.net7实验版)附带的多线程支持一起使用

    https://github.com/dotnet/runtime/blob/main/src/mono/wasm/features.md https://github.com/dotnet/runtime/blob/main/src/mono/wasm/threads.md#JS-interop-on-dedicated-threads

    这是我的基本代码

    <p role="status">Current text: @screenData</p>
    <button class="btn btn-primary" @onclick="ButtonClicked">Click me</button>
    
    @code {
        private string screenData = "";
    
        private async void ButtonClicked()
        {
            Console.WriteLine("Message1,MyThreadID:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
    
            screenData = "AfterMessage1";
    
            await Task.Run(async () =>
            {
                Console.WriteLine("Message2,MyThreadID:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
    
                await Task.Delay(1000);
    
                Console.WriteLine("Message3,MyThreadID:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
    
                await InvokeAsync(() => { screenData = "AfterMessage3"; Console.WriteLine("Message4,MyThreadID:" + System.Threading.Thread.CurrentThread.ManagedThreadId); });
    
            });
    
            Console.WriteLine("Message5,MyThreadID:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
    
            screenData = "AfterMessage5";
    
        }
    }
    

    这是ui不更新时控制台上的输出

    Message1,MyThreadID:1
    Message2,MyThreadID:2
    Message3,MyThreadID:4
    Message4,MyThreadID:4
    Message5,MyThreadID:1
    

    (编辑:我第二次点击按钮时可以看到ui标签更新为“AfterMessage5”,但这是第一次点击的结果)

    如何从子线程调用threadid1(ui线程)?(假设我正在做一个长时间(几秒钟)的后台工作,并想用结果更新ui)只是我不知道如何让子线程与ui线程对话


    作为一种行为信息,当启用“多线程”模式时,即使是以下简单代码也不会更新标签。似乎等待创建了一个子线程。当禁用多线程时,代码可以工作。

        private async void ButtonClicked()
        {
            await Task.Delay(100);
            screenData = "Text To Label";
        }
    

    有没有人经历过blazor wasm多线程?

    当做

    恩德

    2 回复  |  直到 2 年前
        1
  •  2
  •   Mohammad Aghazadeh    2 年前

    因为您正在从另一个更新状态 Thread 您应该显式调用 StateHasChanged(); 强制重新渲染组件

    另一点是,你应该使用 async Task 而不是 async void more info

    await Task.Run(async Task? () =>
    {              
        await InvokeAsync(() => 
        {
           \\your code
           StateHasChanged();
        });
    });
    
    screenData = "AfterMessage5";
    
    StateHasChanged();
    

    根据你的评论,我更改了你的代码,并将其放在下面

    @rendermode InteractiveWebAssembly  
    
    <p role="status">Current text: @screenData</p>
    <button class="btn btn-primary" @onclick="ButtonClicked">Click me</button>
    
    @code {
        private string screenData = "";
    
        private async void ButtonClicked()
        {
            Console.WriteLine("Message1,MyThreadID:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
    
            screenData = "AfterMessage1";
    
            await Task.Run(async Task? () =>
            {
                Console.WriteLine("Message2,MyThreadID:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
    
                await Task.Delay(2000);
    
                Console.WriteLine("Message3,MyThreadID:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
    
                await InvokeAsync(() =>
                {
                   screenData = "AfterMessage3"; Console.WriteLine("Message4,MyThreadID:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
                   StateHasChanged(); 
                });
    
                await Task.Delay(2000);
            });
    
            Console.WriteLine("Message5,MyThreadID:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
    
            screenData = "AfterMessage5";
    
            StateHasChanged();
    
        }
    }
    
    
        2
  •  0
  •   Ender KARADAG    2 年前

    在任务之后调用StateHasChanged()。运行已完成(作为
    @Mohammad Aghazadeh提到)如预期运行。但是如果我想更新子线程中的ui呢。在子线程内部调用StateHasChanged()似乎对ui没有影响

    对此有何评论?