StateHasChanged 不在异步调用 Blazor 服务器应用程序上执行

Sim*_*on3 5 blazor blazor-server-side

当用户按下特定按钮时,我需要在按钮内显示动画并禁用它(调用的方法需要几秒钟才能完成)。这是我的html:

 <div class="row">
            <div class="col-lg-4">
                @if (IsDownloading)
                {
                    <button class="btn btn-primary float-right search disabled" disabled><span class='fa-left fas fa-sync-alt spinning'></span>Downloading...</button>
                }
                else
                {
                    <button id="REC_PDF" class="btn btn-primary" @onclick="@(()=>getPDF())">Download Labels</button>
                }
                
            </div>
        </div>
Run Code Online (Sandbox Code Playgroud)

这是我的代码:

protected bool IsDownloading { get; set; }

public async Task getPDF()
{
    IsDownloading = true;
    StateHasChanged();

    await generate_pdf(labels);

    IsDownloading = false;
    StateHasChanged();
}

private async Task generate_pdf(List<Tuple<string, string, string, string>> filtered_label)
{
    loading = true;
    string PDF_PATH = "./PDF/" + CurrentValue;
    foreach (Tuple<string,string,string,string> label in filtered_label)
    {

        if (!Directory.Exists(PDF_PATH))
        {
            Directory.CreateDirectory(PDF_PATH);
        }
.......
Run Code Online (Sandbox Code Playgroud)

代码正在工作,但由 StateHasChanged() 调用的页面呈现;当方法 getPDF(以及generate_PDF)完全执行时,执行 2 次。

我需要在第一次调用时进行页面渲染以显示 css 加载动画。

(正如其他帖子中所建议的,我使用了 InvokeAsync(() => StateHasChanged()); 但不起作用)

谢谢。

MrC*_*tis 8

Blazor 中的点击事件处理方式如下:

var task = InvokeAsync(EventMethod);
StateHasChanged();
if (!task.IsCompleted)
{
    await task;
    StateHasChanged();
}
Run Code Online (Sandbox Code Playgroud)

注意StateHasChanged实际上并不重新渲染组件,它只是RenderFragment在渲染队列上堆叠一个委托。

所有代码都在 UI 同步上下文上运行,因此通过调用排队的渲染事件StateHasChanged仅会执行:

  • 此时事件方法产生控制权
  • 如果最后没有发生任何收益(因为任务块内只有同步代码)。

我看不到您的 中产生的任何代码generate_pdf

请尝试以下操作:

public async Task getPDF()
{
    IsDownloading = true;
    await Task.Yield();

    await generate_pdf(labels);

    IsDownloading = false;
}
Run Code Online (Sandbox Code Playgroud)

注意:Directory.CreateDirectory不是异步方法。仅FileStream具有异步方法。