在Blazor中为嵌套(而不是第一个或最后一个)方法维护SynchronizationContext [英] Maintaining SynchronizationContext for nested (not first or last) methods in Blazor

查看:89
本文介绍了在Blazor中为嵌套(而不是第一个或最后一个)方法维护SynchronizationContext的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在.NetCore 3.1中创建新的blazor服务器端项目时,使用随Visual Studio 2019加载的默认项目,请考虑以下示例(对自己的计数器示例页面稍作更改):

Using the default project that loads with Visual Studio 2019 when you create a new blazor server-side project in .NetCore 3.1, consider the following example (a slight change to their own counter example page):

<button class="btn btn-primary" @onclick="SingleMethodUpdate">Click Me</button>
<label>Update from same method: @result</label>
<button class="btn btn-primary" @onclick="NestedMethodUpdate">Click Me</button>
<label>Update from nested method: @nestedResult</label>

后面的代码如下:

int result = 0;
int nestedResult = 0;
int nestedCounter = 0;

protected async Task SingleMethodUpdate()
{
    result++;
}

protected async Task NestedMethodUpdate()
{
    await NestedUpdate(++nestedCounter);
    await Task.Delay(1000);
    await NestedUpdate(++nestedCounter);
    await Task.Delay(1000);
    await NestedUpdate(++nestedCounter);
}

protected Task NestedUpdate(int update)
{
    nestedResult = update;
    return Task.FromResult(0);
}

第一个按钮和标签很简单,请按一个按钮,然后按预期按一下即可更新UI上的计数.但是,第二个按钮更复杂.

The first button and label is simple, press a button and the count on the UI updates as soon as you press it as expected. However, the second button is more complicated.

这是中间的await NestedUpdate(++nestedCounter)调用,没有反映在UI上.第一个调用和最后一个调用(第一个和最后一个嵌套方法调用)都实时反映在UI上,因此您将看到:

It is the middle await NestedUpdate(++nestedCounter) call that doesn't get reflected on the UI. The first call and the last call (first and last nested method call) are both reflected in real-time on the UI, so what you see is:

Update from nested method: 1
*2 seconds go by
Update from nested method: 3

我意识到这是由于SynchronizationContext的警告引起的,但是我对如何捕获和维护该上下文以使每个awaited方法在内部被调用感到好奇.我的按钮按下事件使用相同的上下文,因此UI将在代码执行时实时更新.有没有一种不错的/漂亮的方法来做到这一点?

I realize this is because of the caveats with SynchronizationContext but I am more curious as to how I would go about capturing and maintaining that context such that every awaited method that is called within my button press event uses that same context so that the UI will update in real-time as the code executes. Is there a nice/pretty way to do this?

推荐答案

我意识到这是由于SynchronizationContext的警告

I realize this is because of the caveats with SynchronizationContext

不,不是这样.所有这些代码应异步运行,但应在主线程上按顺序运行.
没问题,也不需要使用SyncContext进行修复.

No, not really. All this code should run async but sequentially on the main thread.
Nothing wrong or in need of fixing with the SyncContext here.

您看到的是由于StateHasChanged()逻辑所致,它实际上是关于状态的,大概只是一个布尔标志.

What you see is due to the StateHasChanged() logic, which really is about a State, presumably just a boolean flag.

Blazor框架将在调用事件处理程序之前和之后设置此标志,但是在中间,您必须自己进行设置.

The Blazor framework will set this flag before and after it calls your eventhandler but in the middle you will have to do so your self.

快速修复和说明:

protected async Task NestedMethodUpdate()
{
    // the flag is pre-set here
    await NestedUpdate(++nestedCounter);
    // the thread is available and Blazor will render '1' and reset the flag
    await Task.Delay(1000);  

    await NestedUpdate(++nestedCounter);
    // the thread is available but the flag is down: the '2' is not shown
    await Task.Delay(1000);

    await NestedUpdate(++nestedCounter);
    StatehasChanged();  // <<-- add this
    // the thread is available and the flag is up: the '3' is shown
    await Task.Delay(1000);

    // you can add more steps
    await NestedUpdate(++nestedCounter);
    StatehasChanged();  // <<-- set the flag
    await Task.Delay(1000);  // show '4'

    // this result will show '5' after the method has completed
    await NestedUpdate(++nestedCounter);
}

这篇关于在Blazor中为嵌套(而不是第一个或最后一个)方法维护SynchronizationContext的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆