【问题标题】:Blazor: Component doesn't update every time the for loop spinsBlazor:每次 for 循环旋转时组件都不会更新
【发布时间】:2020-07-03 01:46:57
【问题描述】:

我目前正在处理一个 Blazor 项目并面临一个错误。计划是每秒更新一个组件,只要 for 循环更新。我的问题有点复杂,所以我在另一个项目中重现了这个bug:

进行计算的Calculate.cs文件:

public class Calculate
{
    public void Calc(Index index)
    {
        for (int i = 0; i < 10; i++)
        {
            Thread.Sleep(1000);
            index.Update(i);
        }
    }
}

index.razor 文件:

<button class="btn btn-primary" @onclick="Test">Click me</button>

<p>Test number: @testNumber</p>

@code
{
    private int testNumber;
    Calculate c = new Calculate();

    public void Test()
    {
        c.Calc(this);   
    }
    public void Update(int i)
    {
        testNumber = i;
        Debug.WriteLine(i);
    }
}

测试后,调试控制台每秒打印数字,从 0 到 9,但打开的 Blazor 显示只打印 9,只要计算和 10 秒结束。

【问题讨论】:

  • 我不完全确定您当前的设计要达到什么目的。但是,在现实世界的应用程序中,您应该将 Calculate 类设置为可以注入到组件中的服务,并且该服务可以实现状态模式和通知模式。一般来说,你的服务为你的组件提供计算等服务,当它们准备好时,它应该调用一个事件委托来通知订阅者该事件,并在必要时将事件参数传递给他们,例如计算结果。
  • 你当然不能将组件的实例传递给一个类,以便它可以调用组件的方法。再次,公开事件。这就是我们多年来编码的方式。

标签: c# .net razor blazor blazor-server-side


【解决方案1】:

将此添加到您的 for 循环代码中。

StateHasChanged();

强制刷新。

如果你想看看我的精灵组件,我有一个简单动画的示例:

https://github.com/DataJuggler/DataJuggler.Blazor.Components

这里有一个视频:

https://www.youtube.com/watch?v=frtetHgfdIo

【讨论】:

  • 是的,我已经尝试过使用 StateHasChanged() 但不幸的是它没有任何改进。从字面上看,如果我添加 StateHasChanged() :/
  • 有同样的问题。前任。在进行 api 调用后,循环项目并设置 IsChecked = false,但它们在 UI 中保持选中状态。尝试过 StateHasChanged() 并使用 InvokeAsync() 无济于事。你解决了吗/
【解决方案2】:

这仅在您可以使进程异步时才有效。

为此,将 for 循环移至 Test() 方法,并使其成为 Task 返回方法。剃刀代码可以保持原样。

public Task Test()
{
   for (int i = 0; i < 10; i++)
   {
       await Task.Run( _ =>  c.CalcSubTask(this));   

       Update(i);        
       StateHasChanged();
       await Task.Delay(1);
   }
}

请注意,这只会在 Blazor/Server 中以可接受的方式执行。在 Wasm 项目中,您只有 1 个线程,这会锁定您的 UI。


再想一想,您可以通过使 Calc 方法也异步和 await Update() 方法来保持当前结构。然后 Update() 可以等待 Task.Delay(1)。

确保您有一个从 Test() 方法到 Calc 方法并返回到 Update() 的有效等待链。

更新方法如下所示

public async Task Update(int i)
{
    testNumber = i;
    Debug.WriteLine(i);
    await InvokeAsync(StatHasChanged();  // could be running on another Thread
    await Task.Delay(1);
}

【讨论】:

  • 第二个是我需要的,它有效!谢谢!
【解决方案3】:

您是否尝试将 i 的值分配给 for 循环内的临时变量,如下所示?:

var counter = i;
index.Update(counter);

【讨论】:

    猜你喜欢
    • 2015-04-02
    • 1970-01-01
    • 2021-08-26
    • 1970-01-01
    • 1970-01-01
    • 2011-08-16
    • 1970-01-01
    • 2018-12-24
    • 2016-04-12
    相关资源
    最近更新 更多