为什么页面繁忙时鼠标移动事件会被丢弃?

问题描述 投票:0回答:1

看到这个 Blazor 小提琴:https://blazorfiddle.com/s/rckyjgd5

页面上有一个红色框。它具有“onmousemove”和“onclick”事件的处理程序。其中每一个都会导致计数增加。计数值显示在页面上。

页面上还有 4 个按钮。这些按钮会导致进行耗时的计算,但它们的执行方式略有不同。 (如果您的机器比我使用的机器快得多或慢得多,那么您可能需要调整 NumberOfIterations 属性的值,以便计算需要适当的时间 - 几秒钟是理想的。)

  • 第一个按钮同步执行计算。
  • 第二个按钮被声明为异步函数,但与第一个按钮一样,它实际上同步执行计算,因为它在任何地方都没有使用“await”关键字。
  • 第三个按钮是异步的。在计算过程中,它偶尔会调用 Task.Yield()。
  • 第四个按钮是异步的。它偶尔会调用一个较小值的 Task.Delay() 。

这个小提琴的目的是为了我自己的学习,探索异步代码在 Blazor 中的工作原理以及如何中断耗时的代码以使 UI 保持响应。对于我要问的问题来说,小提琴有点过分了。

这里有一种行为我觉得很奇怪。如果开始计算(使用前 3 个按钮之一)并且我将鼠标移动到红色方块上,则在计算发生时应发生的鼠标移动事件似乎被丢弃。在页面繁忙期间或之后,计数不会更新。但是,如果开始计算并单击红色方块,则计数会在计算完成后更新。如果我在计算运行时点击红色方块 5 次,那么当计算完成时,计数将跳增 5。因此这些事件不会被丢弃 - 它们被延迟,但它们最终会发生。

第三个按钮的行为与前两个按钮的行为相同,这一事实可以通过发布到这 2 个 Stack Overflow 问题(第一个第二个)的答案来解释。

如果使用第四个按钮开始计算,并且我将鼠标指针移动到红色方块上,则鼠标移动事件的计数会偶尔更新。在某些时间间隔中,当我移动鼠标时,计数将更新,并且在某些时间间隔中,鼠标事件被“删除”。如果我用鼠标单击,那么所有事件都会发生,并且不会有太大的延迟,但是在浏览器繁忙时发生的事件会聚集在一起。

从这些观察看来:

  • 浏览器“忙”时发生的鼠标移动事件将被简单地丢弃。就好像它们从未发生过一样。
  • 浏览器“忙”时发生的点击事件会排队,一旦浏览器不再“忙”,它们就会生效。

问题:

  • 为什么鼠标移动和单击事件的行为存在差异?
  • 这是我构造小提琴的结果吗?
  • 这是浏览器的 JavaScript 执行模型应该如何工作的结果吗? (或者它应该如何根据相关标准工作,或者它如何在我尝试过的浏览器中工作?)
  • 这是 WASM 工作方式的结果吗? (或者它应该如何按照标准工作,或者它如何在我尝试过的浏览器中工作?)
  • 这是 Blazor WebAssembly 实现方式的结果吗?
  • 这种行为的可靠性如何? (在未来版本的浏览器中,在未来版本的 .NET 和 Blazor WebAssembly 中?)(根据 Blazor Fiddle 网站的表述,我相信它目前使用 .NET 6.0。)

我尝试使用的浏览器是 Microsoft Edge(64 位版本 123.0.2420.65)和 Mozilla Firefox(版本 123.0)。两者都表现出相同的行为。

blazor mouseevent blazor-webassembly
1个回答
0
投票

小提琴可以成为很好的 MRE。

前 2 个按钮的方法完全相同,当您将

async
应用于某个方法时,它会更改该方法的实现并 enables 等待。如果你不等待任何事情,那就有点浪费了。对于调用者来说没有区别。

这两个按钮都会阻塞 UI 线程并阻止更新,因此结果行为是预期的。

接下来的 2 个按钮仅在使用 Yield()

Delay(1)
 方面有所不同。

当您在 Blazor Server 上运行此代码时,它们的行为应该相同。在 Wasm 上,Yield() 不会导致任务切换,因为

SynchronizationContext.Current is null

 为 true。

© www.soinside.com 2019 - 2024. All rights reserved.