Blazor计时器调用异步API任务以更新UI

Blazor计时器调用异步API任务以更新UI,blazor,blazor-server-side,Blazor,Blazor Server Side,我正在Blazor服务器端页面中设置计时器。目标是每x秒调用一个API,并根据返回值更新UI 我得到了这个密码: private string Time { get; set; } protected override void OnInitialized() { var timer = new System.Threading.Timer((_) => { Time = DateTime.Now.ToString(); InvokeAsy

我正在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();
}
  private string Time { get; set; }

protected override void OnInitialized()
{
    base.OnInitialized();
    var timer = new System.Threading.Timer((_) =>
    {

        InvokeAsync( async ()  =>
        {
            Time = await GetValue();
            StateHasChanged();
        });
    }, null, 0, 1000);

}
这个很好用。UI每秒更新一次新的时间值。但是,我不知道如何调用异步任务来获取值。我想换一条线:

Time = DateTime.Now.ToString();
使用调用以下函数的行:

private async Task<string> GetValue()
{
    var result = await _api.GetAsync<StringDto>("/api/GetValue");
    return result.Text;
}
但我收到了以下错误:

The current thread is not associated with the Dispatcher. Use InvokeAsync() to switch execution to the Dispatcher when triggering rendering or component state.
调用异步方法需要做什么

非常感谢

请尝试以下代码:

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();
}
  private string Time { get; set; }

protected override void OnInitialized()
{
    base.OnInitialized();
    var timer = new System.Threading.Timer((_) =>
    {

        InvokeAsync( async ()  =>
        {
            Time = await GetValue();
            StateHasChanged();
        });
    }, null, 0, 1000);

}
GetValue方法应为:

private async Task<string> GetValue()
{
    return await _api.GetAsync<StringDto>("/api/GetValue");
  
}
请尝试以下代码:

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();
}
  private string Time { get; set; }

protected override void OnInitialized()
{
    base.OnInitialized();
    var timer = new System.Threading.Timer((_) =>
    {

        InvokeAsync( async ()  =>
        {
            Time = await GetValue();
            StateHasChanged();
        });
    }, null, 0, 1000);

}
GetValue方法应为:

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

您可能不想调用GetValue,这将是毫无意义的。您可以这样实现计时器:

System.Threading.Timer timer;
protected override void OnInitialized()
{
    timer = new System.Threading.Timer(async _ =>
    {
        Time = await GetValue();
        await InvokeAsync(StateHasChanged);
    }, null, 0, 1000);
}
我使用了一个字段来存储计时器,因为您应该处理它,请将此添加到Razor部分:

@implements IDisposable
这与守则有关:

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

您可能不想调用GetValue,这将是毫无意义的。您可以这样实现计时器:

System.Threading.Timer timer;
protected override void OnInitialized()
{
    timer = new System.Threading.Timer(async _ =>
    {
        Time = await GetValue();
        await InvokeAsync(StateHasChanged);
    }, null, 0, 1000);
}
我使用了一个字段来存储计时器,因为您应该处理它,请将此添加到Razor部分:

@implements IDisposable
这与守则有关:

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

我喜欢你答案中的一般解决方案,但你是否打算省略对base.OnInitialized的调用?是的,在普通页面中不需要。你可以根据“一般原则”把它放进去,这是品味的问题。请看天气预报页面以获取参考。我喜欢你回答中的一般解决方案,但你是否打算省略呼叫基地。初始化?是的,在正常页面中不需要。你可以根据“一般原则”把它放进去,这是品味的问题。查看天气预报页面以获取参考。