!todo.IsDon-6ren">
gpt4 book ai didi

c# - 异步更新属性

转载 作者:行者123 更新时间:2023-12-03 17:32:02 25 4
gpt4 key购买 nike

当我的 ViewModel 的一个属性被更新时,其他属性被异步更新。

待办事项.cshtml:

@page "/todo"

<h1>Todo (@todos.Count(todo => !todo.IsDone))</h1>

<ul>
@foreach (var todo in todos)
{
<li>
<input type="checkbox" bind="@todo.IsDone" />
<input bind="@todo.Title" />
</li>
}
</ul>

<input placeholder="Something todo" bind="@newTodo"/>
<button onclick="@AddTodo">Add todo</button>

@functions {
IList<TodoItem> todos = new List<TodoItem>();


string newTodo;
void AddTodo()
{
if (!string.IsNullOrWhiteSpace(newTodo))
{
todos.Add(new TodoItem { Title = newTodo });
newTodo = string.Empty;
}
}
}

TodoItem.cs:
public class TodoItem
{
private bool _isDone;

public string Title { get; set; }
public bool IsDone
{
get => _isDone;
set
{
_isDone = value;
Task.Run(() =>
{
//Simulate work
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2));
//Update property
Title = Title + " - Done";
});
}
}
}

在同步(没有 Task.Run)中,这项工作正常,但在异步中,UI 不会更新。

我需要解释要使用 StateHasChanged() 更新的 UI :
https://github.com/aspnet/Blazor/issues/1413

但是我不能在 TodoItem 中调用这个方法(而且我不希望 TodoItem 知道 Blazor 组件)。

您有更新 UI 的解决方案吗?

最佳答案

简单的答案是“修改您的 var 后只需触发 StateHasChanged();”:

        Task.Run(() =>
{
//Simulate work
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2));
//Update property
Title = Title + " - Done";
StateHasChanged();
});

因为您的方法是异步的,所以重写为:
        Task.Run(async () =>  //<--here async
{
//Simulate async work
Task.Run( async () => {
await Task.Run( () => {} ); //<--- await
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2));
});
//Update property
Title = Title + " - Done";
StateHasChanged();
});

为了避免反模式和编写干净的代码,您的 ModelView 可能有一个公共(public)事件来通知 UI 它已更改,只需将此 UI 上的事件连接到 StateHasChanged(); .

我在这里写了修改后的 Blazor Counter 示例:
@page "/counter"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" onclick="@IncrementCount">
Click me @s <!-- here var -->
</button>

@functions {
int currentCount = 0;

string s = "";

void IncrementCount()
{
currentCount++;
Task.Run(() =>
{
//Simulate work
Task.Run( async () => {
await Task.Run( () => {} );
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2));}
);
//Update property
s = s + " - Done";
StateHasChanged();
});
}
}
}

已编辑

调用 StateHasChanged不再支持来自线程。只是改变:
    Task.Run(() =>
{
//Simulate work
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2));
//Update property
Title = Title + " - Done";
StateHasChanged();
});

经过
    Invoke( () =>
{
...

关于c# - 异步更新属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53364149/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com