Blazor タイマーは非同期 API タスクを呼び出して UI を更新します 質問する

Blazor タイマーは非同期 API タスクを呼び出して UI を更新します 質問する

Blazor サーバー側ページでタイマーを設定しています。目標は、x 秒ごとに API を呼び出し、戻り値に基づいて UI を更新することです。

私はこのコードを取得しました:

private string Time { get; set; }

protected override void OnInitialized()
{
    var timer = new System.Threading.Timer((_) =>
    {
        Time = DateTime.Now.ToString();
        InvokeAsync(() =>
        {
            StateHasChanged();
        });
    }, null, 0, 1000);
    base.OnInitialized();
}

これは見事に動作します。UI は新しい時間値で毎秒更新されました。ただし、値を取得するために非同期タスクを呼び出す方法がわかりません。次の行を置き換えたいと思います。

Time = DateTime.Now.ToString();

次の関数を呼び出す行を追加します。

private async Task<string> GetValue()
{
    var result = await _api.GetAsync<StringDto>("/api/GetValue");
    return result.Text;
}

この行を試してみました:

Time = GetValue().Result;

しかし、次のようなエラーが発生しました:

The current thread is not associated with the Dispatcher. Use InvokeAsync() to switch execution to the Dispatcher when triggering rendering or component state.

非同期メソッドを呼び出すには何をする必要がありますか?

本当にありがとう!

ベストアンサー1

おそらく GetValue() を Invoke() することは望ましくないでしょう。それはむしろ無意味です。タイマーは次のように実装できます。

System.Threading.Timer timer;
protected override void OnInitialized()
{
    timer = new System.Threading.Timer(async _ =>  // async void
    {
        Time = await GetValue();
        // we need StateHasChanged() because this is an async void handler
        // we need to Invoke it because we could be on the wrong Thread          
        await InvokeAsync(StateHasChanged);
    }, null, 0, 1000);
}

タイマーは破棄する必要があるため、タイマーを保存するためのフィールドを使用しました。Razor セクションに以下を追加します。

@implements IDisposable

コードにこれを追加します:

public void Dispose()
{
    timer?.Dispose();
}

おすすめ記事