gpt4 book ai didi

blazor - 在 Blazor 服务器中,是否保证 js 互操作调用的顺序?

转载 作者:行者123 更新时间:2023-12-03 23:46:36 25 4
gpt4 key购买 nike

鉴于

我有一个 onscroll 或 mousemove javascript eventhandlers,它在服务器上调用一个 C# 方法:

然后

是服务器上保证的 C# 方法调用的顺序 ?

例如以下javascript:

document.body.addEventListener("scroll",(e) => {
DotNet.invokeMethodAsync("BlazorSample", "HandleOnScroll", e)
});

和 C#

@code {
[JSInvokable()]
public static async Task HandleOnScroll()
{
// ...
}
}

一个类似的问题是反过来,从 DotNet 调用到 JS。

最佳答案

简短的回答:是的。

更长的答案:

从 C# 调用到 JavaScript,反之亦然,会立即执行。

然后,对 C# 的调用由 Render Dispatcher 处理,这意味着如果 C# 代码是同步的(或一直向下等待的异步),则对 C# 的每次调用都将在下一次调用开始之前运行完成。

如果 C# 代码是异步的并且不等待异步操作(例如 Task.Delay),则渲染调度程序将在当前方法等待时立即开始运行下一个调用的方法。

多个线程不会同时运行。 Render Dispatcher 不会在 await 之后继续执行代码直到当前调度的任务执行 await或完成。

实际上,Render Dispatcher 序列化了对组件的访问,以便一次只有 1 个线程在任何组件上运行 - 无论有多少线程在它们上运行。

PS:您可以使用 InvokeAsync(......) 来做同样的事情对于由外部刺激触发的任何代码,例如单例服务上另一个用户的线程引发的事件。

如果您想了解有关渲染调度程序如何工作的更多信息,请阅读 Multi-threaded rendering 部分在布拉佐大学。

这里有一些证据:

首先,创建 index.js 并确保它在您的 HTML 页面中被引用 <script src="/whatever/index.js"></script>

window.callbackDotNet = async function (objRef, counter) {
await objRef.invokeMethodAsync("CalledBackFromJavaScript", counter);
}

接下来,更新 Index.razor页面,因此它调用该 JavaScript 并接受回调。
@page "/"
@inject IJSRuntime JSRuntime

<button @onclick=ButtonClicked>Click me</button>

@code
{
private async Task ButtonClicked()
{
using (var objRef = DotNetObjectReference.Create(this))
{
const int Max = 10;
for (int i = 1; i < 10; i++)
{
System.Diagnostics.Debug.WriteLine("Call to JS " + i);
await JSRuntime.InvokeVoidAsync("callbackDotNet", objRef, i);
}

System.Diagnostics.Debug.WriteLine("Call to JS " + Max);
await JSRuntime.InvokeVoidAsync("callbackDotNet", objRef, Max);
}
}

[JSInvokable("CalledBackFromJavaScript")]
public async Task CalledBackFromJavaScript(int counter)
{
System.Diagnostics.Debug.WriteLine("Start callback from JS call " + counter);
await Task.Delay(1000).ConfigureAwait(false);
System.Diagnostics.Debug.WriteLine("Finish callback from JS call " + counter);
}
}


等待整个链,包括 JavaScript,因此输出将如下所示...
Call to JS 1
Start callback from JS call 1
* (one second later)
Finish callback from JS call 1
Call to JS 2
Start callback from JS call 2
* (one second later)
Finish callback from JS call 2

... etc ...

Call to JS 9
Start callback from JS call 9
* (one second later)
Finish callback from JS call 9
Call to JS 10
Start callback from JS call 10
* (one second later)
Finish callback from JS call 10

如果删除 asyncawait来自你的 JavaScript,就像这样
window.callbackDotNet = function (objRef, counter) {
objRef.invokeMethodAsync("CalledBackFromJavaScript", counter);
}

当你运行它时,你会看到对 JavaScript 的调用是正确的 1..10 顺序,而对 C# 的回调是正确的 1..10 顺序,但“完成回调”的顺序是 2、1、4, 3、5、7、6、9、8、10。

这将是由于 C# 内部 .NET 调度等原因,其中 .NET 决定接下来要执行的任务 await Task.Delay(1000) .

如果您恢复 asyncawait在你的 JavaScript 中,然后只有 await在最后一次 C# 调用中,如下所示:
        using (var objRef = DotNetObjectReference.Create(this))
{
const int Max = 10;
for (int i = 1; i < 10; i++)
{
System.Diagnostics.Debug.WriteLine("Call to JS " + i);
_ = JSRuntime.InvokeVoidAsync("callbackDotNet", objRef, i);
}

System.Diagnostics.Debug.WriteLine("Call to JS " + Max);
await JSRuntime.InvokeVoidAsync("callbackDotNet", objRef, Max);
}

然后你会看到以下输出:
Call to JS 1
Call to JS 2
Call to JS 3
Call to JS 4
Start callback from JS call 1
Start callback from JS call 2
Start callback from JS call 3
Start callback from JS call 4
* (one second later)
Finish callback from JS call 1
Finish callback from JS call 2
Finish callback from JS call 3
Finish callback from JS call 4

注意:您的示例代码会导致多个用户同时执行一个静态方法。在您的场景中,您应该调用一个实例方法。

关于blazor - 在 Blazor 服务器中,是否保证 js 互操作调用的顺序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62327543/

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