當您從使用異步的頁面切換到另一個頁面并回傳時,就會出現這種情況。當我回傳時,async 一直在控制臺上作業并且資料正在輸入,但StateHasChanged()似乎無法更新螢屏,即使它是否正常作業。是不是因為執行緒分離的問題導致頁面無法正常更新?(StateHasChanged()和其他功能)在這種情況下,我怎樣才能使我想要識別的現有執行緒?
我搜索了一下,有一個詞關于Synchronization Context,這有幫助嗎?
@page "/push"
<button @onclick="@subscribe">subscribe</button>
<div>
@foreach (var noti in PushNotifications.notifications)
{
<p>@noti</p>
}
</div>
@code {
public async Task subscribe()
{
...
reply = client.subscribe(subscriptionRequest);
try
{
await foreach (var subscriptionResponse in reply.ResponseStream.ReadAllAsync())
{
Console.WriteLine(subscriptionResponse);
PushNotifications.notifications.Add(subscriptionResponse);
await InvokeAsync(StateHasChanged);
await Task.Delay(500);
}
}
}
uj5u.com熱心網友回復:
下面是一些代碼,演示了一種在具有長時間運行的行程的頁面之間維護狀態的方法。
一切都發生在 DI 范圍的服務中。在這種情況下,它只是緩慢地獲取國家串列。有兩種取消機制:取消令牌或設定布林值的方法。
public class DataService
{
public List<string> Countries { get; set; } = new List<string>();
public Action? CountryListUpdated;
public bool Processing { get; private set; }=false;
private bool _cancel = false;
private CancellationToken _cancellationToken = new CancellationToken();
private Task? _task;
public string Message { get; private set; } = "Idle";
public ValueTask GetCountriesAsync(CancellationToken cancellationToken)
{
_cancellationToken = cancellationToken;
_task = this.getCountriesAsync();
return ValueTask.CompletedTask;
}
public ValueTask GetCountriesAsync()
{
_task = this.getCountriesAsync();
return ValueTask.CompletedTask;
}
public async Task getCountriesAsync()
{
this.Processing = true;
this.Message = "Processing";
this.Countries.Clear();
foreach (var country in _countries)
{
this.Countries.Add(country);
this.CountryListUpdated?.Invoke();
await Task.Delay(2500);
if (_cancellationToken.IsCancellationRequested || _cancel)
Debug.WriteLine("GetCountries Cancelled");
}
this.Message = "Processing Complete";
this.Processing = false;
_cancel = false;
this.CountryListUpdated?.Invoke();
}
public void CancelProcessing()
=> _cancel = true;
private List<string> _countries => new List<string> { "UK", "France", "Portugal", "Spain", "Italy", "Germany"};
}
注冊程式:
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddSingleton<WeatherForecastService>();
builder.Services.AddScoped<DataService>();
這是顯示頁面。注意 UI 更新是事件驅動的。
@page "/"
@inject DataService DataService;
@implements IDisposable
<PageTitle>Index</PageTitle>
<div class="m-2 p-2">
<button class="btn btn-danger" disabled="@(!this.DataService.Processing)" @onclick=this.CancelProcessing>Cancel Processing</button>
<button class="btn btn-primary" disabled="@this.DataService.Processing" @onclick=GetData>Get Data</button>
</div>
<div class="alert alert-primary">@this.DataService.Message</div>
@foreach (var country in DataService.Countries)
{
<div>@country</div>
}
@code {
private CancellationTokenSource cancellationToken = new CancellationTokenSource();
protected override void OnInitialized()
=> this.DataService.CountryListUpdated = OnCountryUpdated;
private async Task GetData()
{
await this.DataService.GetCountriesAsync(cancellationToken.Token);
}
private void CancelProcessing()
{
//DataService.CancelProcessing();
this.cancellationToken.Cancel();
}
private void OnCountryUpdated()
=> this.InvokeAsync(StateHasChanged);
public void Dispose()
{
// If you want to cancel the processing when you exit a page
//cancellationToken.Cancel();
this.DataService.CountryListUpdated -= OnCountryUpdated;
}
}
uj5u.com熱心網友回復:
...您使用異步到另一個頁面并回傳。當我回傳時, async 一直在控制臺上作業 [...] ,但 StateHasChanged() 似乎無法更新螢屏
最可能的解釋是您“回傳”到新頁面,但控制臺仍在前一個舊頁面上顯示傳入資料。該頁面仍在記憶體中,但不在螢屏上。應該已經清理干凈了。
第 1 步:當您的頁面代碼創建資源(如 HttpClient)時,您需要:
@implements IDisposable
@code {
...
public void Dispose()
{
// Dispose resources, make sure your subscription loop is canceled.
_httpClient?.Dispose();
...
}
}
我搜索了一下,有一個關于同步背景關系的詞,這有幫助嗎?
不,在 WebAssembly 上運行時,背景關系是null.
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/513481.html
