Blazor StateHasChanged and child parameters (`await Task.Run(StateHasChanged);` vs `await InvokeAsync(StateHasChanged);`)(Blazor StateHasChanged和子参数(`等待Task.Run(StateHasChanged);`vs`等待InvokeAsync(StateHasChanged);`))
问题描述
我最近就Blazor wasmhere中的await Task.Run(StateHasChanged);和await InvokeAsync(StateHasChanged);之间的区别提出了一个问题。
结论是await Task.Run(StateHasChanged);是不正确的,应该避免;使用它会产生与await InvokeAsync(StateHasChanged);相同的结果,但是当线程可用时会出现问题(公认的答案会详细说明)。
我已将我的代码库更新为使用await InvokeAsync(StateHasChanged);,但是我发现两者的结果实际上存在差异。
以下是我的应用程序中问题的最小复制:
家长
<h1>Parent: @title</h1>
<button class="btn btn-primary" @onclick="() => SetBool(true)">True</button>
<button class="btn btn-primary" @onclick="() => SetBool(false)">False</button>
<Child Bool="@Bool" @ref="Child"></Child>
@code {
    private bool Bool = false;
    private Child Child;
    private string title;
    private async void SetBool(bool name)
    {
        Bool = name;
        title = Bool ? "True" : "False";
        // NOTE: This will work as expected; Child will be updated with the Parent
        // await Task.Run(StateHasChanged);
        // NOTE: This will only update the Child the second time it is clicked
        await InvokeAsync(StateHasChanged);
        await Child.Trigger();
    }
}
子级
<h3>Child: @title</h3>
@code {
    [Parameter]
    public bool Bool { set; get; } = false;
    private string title;
    public async Task Trigger()
    {
        title = Bool ? "True" : "False";
        await InvokeAsync(StateHasChanged);
    }
}
单击父项中的True或False按钮应同时更新父项和子项中的Bool值。请注意,title变量仅用于可视化显示Bool值。
使用await Task.Run(StateHasChanged);将导致父对象和子对象的状态同时更新。另一方面,await InvokeAsync(StateHasChanged);将更新父组件,但不会更新子组件;需要单击两次a按钮才能获得子组件中各自的值。
我将此值传递给子组件的方式有问题吗?
请注意,不能使用await Task.Run(StateHasChanged);;这样做意味着我无法使用bUnit测试组件。
复制代码可用here。
推荐答案
以下代码片段介绍了应该如何编码:
Parent.razor
<h1>Parent: @title</h1>
<button class="btn btn-primary" @onclick="() => SetBool(true)">True</button>
<button class="btn btn-primary" @onclick="() => SetBool(false)">False</button>
<Child Bool="@Bool" @ref="Child"></Child>
@code {
    private bool Bool = false;
    private Child Child;
    private string title;
    protected override void OnInitialized()
    {
        title = Bool ? "True" : "False";
    }
    private async Task SetBool(bool name)
    {
        Bool = name;
        title = Bool ? "True" : "False";
        
        await Task.CompletedTask;
    }
}
Child.razor
<h3>Child: @title</h3>
@code {
    [Parameter]
    public bool Bool { set; get; } = false;
    private string title;
    private bool _Bool;
    public async Task Trigger()
    {
        title = _Bool ? "True" : "False";
        await InvokeAsync(StateHasChanged);
    }
    protected override async Task OnParametersSetAsync()
    {
        _Bool = Bool;
        await Trigger();
      
    }
}
注意:您面临的问题不是因为使用Task.Run(StateHasChanged); and await InvokeAsync(StateHasChanged);,尽管结果不同。您根本没有遵循Blazor组件模型规则。您是否意识到,当您单击
SetBool按钮时,父组件将重新呈现,因为它的状态已更改。因此,子组件使用Bool==true重新呈现,但是您在屏幕上看不到这一点,因为更改子组件中的标题的代码被放在Trigger方法中,该方法仅从父组件调用。您的假设是错误的。请勿修改或更改Bool参数属性的状态。定义一个局部变量来存储参数属性的值,您可以随心所欲地操作其值。换句话说,零部件参数特性应定义为自动特性.它们是Blazor框架将值从父组件传递到其子组件的DTO。
不要不必要地从UI事件处理程序调用StateHasChanged方法。自动调用。
请勿使用
async void.使用async Task.当您使用async void时,Blazor不会计算异步方法何时完成,因此它不会调用StateHasChanged方法避免使用
Task.Run。我从来不用。我甚至不记得为什么我不应该 用它吧。我就是不用它。
这篇关于Blazor StateHasChanged和子参数(`等待Task.Run(StateHasChanged);`vs`等待InvokeAsync(StateHasChanged);`)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:Blazor StateHasChanged和子参数(`等待Task.Run(StateHasChanged);`vs`等待InvokeAsync(StateHasChanged);`)
				
        
 
            
        基础教程推荐
- JSON.NET 中基于属性的类型解析 2022-01-01
 - 是否可以在 asp classic 和 asp.net 之间共享会话状态 2022-01-01
 - 错误“此流不支持搜索操作"在 C# 中 2022-01-01
 - 从 VS 2017 .NET Core 项目的发布目录中排除文件 2022-01-01
 - 在 VS2010 中的 Post Build 事件中将 bin 文件复制到物 2022-01-01
 - 全局 ASAX - 获取服务器名称 2022-01-01
 - 将事件 TextChanged 分配给表单中的所有文本框 2022-01-01
 - 经典 Asp 中的 ResolveUrl/Url.Content 等效项 2022-01-01
 - 首先创建代码,多对多,关联表中的附加字段 2022-01-01
 - 如何动态获取文本框中datagridview列的总和 2022-01-01
 
    	
    	
    	
    	
    	
    	
    	
    	
						
						
						
						
						
				
				
				
				