InvokeAsync 與 StateHasChanged 非同步刷新UI問題 (MessageBus 應用)
Blazor Comonent 的 StateHasChanged() 在 Message Bus 觸發 UI render 無效問題解決。BlazorComponentBus,MessageBus.
引言
解決方法
先下結論
關鍵程式碼紀錄
沒圖沒真象

參考文章
Last updated
Blazor Comonent 的 StateHasChanged() 在 Message Bus 觸發 UI render 無效問題解決。BlazorComponentBus,MessageBus.

Last updated
await InvokeAsync(() => StateHasChanged());@page "/DEMO007"
@inject SampleBiz bizSvc
@inject BlazorComponentBus.ComponentBus busSvc
<PageTitle>各項機制測試</PageTitle>
@* 命令列 *@
<MudStack Row Justify=Justify.Center Class="my-4">
<MudButton Variant=Variant.Filled OnClick=HandlePostSnack>測試送 NotifyMessage 法一</MudButton>
<MudButton Variant=Variant.Filled OnClick=HandlePostSnack2>測試送 NotifyMessage 法二</MudButton>
</MudStack>
@* 接收 Message Bus 訊息 *@
<NotifyMessageResp />
@code {
void HandlePostSnack()
{
// 送出一個訊息
busSvc.Publish(new NotifyMessage { Message = "我出運了!" });
}
async Task HandlePostSnack2()
{
// 在後端商業邏輯層送出數個訊息,並將反應到前端
await Task.Run(() => bizSvc.SimsLongtermProcedure(/* Args */));
}
}///
/// 此元件專用來接收 Message Bus 訂閱訊息
///
@implements IDisposable
@inject BlazorComponentBus.ComponentBus busSvc
@inject ISnackbar snackSvc
@foreach (var msg in msgList)
{
<p>@($"{msg.Message} at {msg.MsgTime:HH:mm:ss}")</p>
}
@code {
List<NotifyMessage> msgList = new();
void IDisposable.Dispose()
{
busSvc.UnSubscribe<NotifyMessage>(HanldeNotifyMessageAsync);
//※ 記得有訂閱就要解訂閱。
}
protected override void OnInitialized()
{
base.OnInitialized();
// 訂閱訊息
busSvc.Subscribe<NotifyMessage>(HanldeNotifyMessageAsync);
}
async Task HanldeNotifyMessageAsync(BlazorComponentBus.MessageArgs args, CancellationToken ct)
{
// 取出訊息
var msg = args.GetMessage<NotifyMessage>();
// 以 toast/snackbar 呈現訊息
snackSvc.Add($"{msg.Message} at {msg.MsgTime:HH:mm:ss}");
// 或呈現(反應)到主頁面
msgList.Add(msg);
await InvokeAsync(() => StateHasChanged()); /// <----- 訊息銜接回主體
}
}class SampleBiz
{
//## injection
readonly ILogger<SampleBiz> _logger;
readonly BlazorComponentBus.ComponentBus _busSvc;
public SampleBiz(ILogger<SampleBiz> logger, IAuthUser BlazorComponentBus.ComponentBus busSvc)
{
_logger = logger;
_busSvc = busSvc;
}
public List<DataInfo> SimsLongtermProcedure(args)
{
_busSvc.Publish(new NotifyMessage { Message = "某處理程序:開始" });
// 模擬跑一段時間(3秒)
SpinWait.SpinUntil(() => false, 3000);
_busSvc.Publish(new NotifyMessage { Message = "某處理程序:步驟二" });
// 模擬跑一段時間(3秒)
SpinWait.SpinUntil(() => false, 3000);
_busSvc.Publish(new NotifyMessage { Message = "某處理程序:步驟三" });
// 模擬跑一段時間(3秒)
SpinWait.SpinUntil(() => false, 3000);
_busSvc.Publish(new NotifyMessage { Message = "某處理程序:結束" });
return dataList;
}
}