blazor服务器应用程序中的频繁页面更新

blazor服务器应用程序中的频繁页面更新,blazor,blazor-server-side,Blazor,Blazor Server Side,在blazor服务器应用程序中,可以经常发送事件并调用statehaschange,例如每秒500次吗 我的一个页面需要对外部事件做出反应,然后相应地更新其状态。我找到了以下解决方案: 创建一个检测外部事件并调用C#事件的服务 将服务注入razor页面 在页面中,连接到事件并在处理程序中调用InvokeAsync(()=>StateHasChanged()) 这已经正常工作了。但是,该事件可能经常发生,例如每秒500次,我担心客户端和服务器的性能。不幸的是,我不知道哪一部分发生在服务器上,哪

在blazor服务器应用程序中,可以经常发送事件并调用
statehaschange
,例如每秒500次吗

我的一个页面需要对外部事件做出反应,然后相应地更新其状态。我找到了以下解决方案:

  • 创建一个检测外部事件并调用C#事件的服务
  • 将服务注入razor页面
  • 在页面中,连接到事件并在处理程序中调用
    InvokeAsync(()=>StateHasChanged())
这已经正常工作了。但是,该事件可能经常发生,例如每秒500次,我担心客户端和服务器的性能。不幸的是,我不知道哪一部分发生在服务器上,哪一部分发生在客户机上,哪一部分在它们之间发送

  • 这些事件是否每秒从服务器发送500次到客户端?我认为这将消耗大量带宽
  • 客户端是否在每次调用
    statehaschange
    后实际呈现页面?我认为这会给客户端带来很高的CPU负载

    • 为了回答您的一些问题,当您在服务器模式下运行时,所有实际工作都在Blazor Hub会话中进行

      调用
      StateHasChanged
      真正做的是将
      RenderFragment
      排队到中心会话中的渲染器队列中。下面是
      ComponentBase
      中的代码位

                 _renderFragment = builder =>
                  {
                      _hasPendingQueuedRender = false;
                      _hasNeverRendered = false;
                      BuildRenderTree(builder);
                  };
      
      状态已更改
      如下所示:

             protected void StateHasChanged()
              {
                  if (_hasPendingQueuedRender) return;
                  if (_hasNeverRendered || ShouldRender())
                  {
                      _hasPendingQueuedRender = true;
                      try
                      {
                          _renderHandle.Render(_renderFragment);
                      }
                      catch
                      {
                          _hasPendingQueuedRender = false;
                          throw;
                      }
                  }
              }
      
      StateHasChanged
      仅在新渲染事件尚未排队时对其排队。渲染后,渲染器扩散引擎会检测到任何更改,并通过Signal将这些更改发送到客户端浏览器会话


      所以没有变化,没有客户机活动,只有大量服务器绑定的活动来处理事件并解决任何变化。对服务器的影响将取决于您可用的服务器功率。

      要回答您的一些问题,在服务器模式下运行时,所有实际工作都将在Blazor Hub会话中进行

      调用
      StateHasChanged
      真正做的是将
      RenderFragment
      排队到中心会话中的渲染器队列中。下面是
      ComponentBase
      中的代码位

                 _renderFragment = builder =>
                  {
                      _hasPendingQueuedRender = false;
                      _hasNeverRendered = false;
                      BuildRenderTree(builder);
                  };
      
      状态已更改
      如下所示:

             protected void StateHasChanged()
              {
                  if (_hasPendingQueuedRender) return;
                  if (_hasNeverRendered || ShouldRender())
                  {
                      _hasPendingQueuedRender = true;
                      try
                      {
                          _renderHandle.Render(_renderFragment);
                      }
                      catch
                      {
                          _hasPendingQueuedRender = false;
                          throw;
                      }
                  }
              }
      
      StateHasChanged
      仅在新渲染事件尚未排队时对其排队。渲染后,渲染器扩散引擎会检测到任何更改,并通过Signal将这些更改发送到客户端浏览器会话


      所以没有变化,没有客户机活动,只有大量服务器绑定的活动来处理事件并解决任何变化。对服务器的影响将取决于您可用的服务器功率。

      看来Blazor服务器每秒可以发送数百个更改:

      @page/“
      每秒Tics:@CurrentValue
      

      @DateTime.Now.ToString(“HH:mm:ss”) 渲染数量:@nRenders.ToString(“N0”) 开始 .球{宽度:30px;高度:30px;顶部:-10px; 位置:绝对;背景色:蓝色;} @代码 { Int64 nRenders=0,v=1,位置=10,电流值=10; 字符串位置_txt=>$“左:{position}px;”; private static System.Timers.Timer aTimer=new System.Timers.Timer(); 受保护的void start() { move(); aTimer.appead+=(源代码,e)=>move(); aTimer.AutoReset=true; aTimer.Enabled=!aTimer.Enabled; } 受保护的无效移动() { aTimer.间隔=1000.0/当前值; 位置=(位置+v); 如果(位置>500 | |位置nRenders++); }
      看来Blazor服务器每秒可以发送数百个更改:

      @page/“
      每秒Tics:@CurrentValue
      

      @DateTime.Now.ToString(“HH:mm:ss”) 渲染数量:@nRenders.ToString(“N0”) 开始 .球{宽度:30px;高度:30px;顶部:-10px; 位置:绝对;背景色:蓝色;} @代码 { Int64 nRenders=0,v=1,位置=10,电流值=10; 字符串位置_txt=>$“左:{position}px;”; private static System.Timers.Timer aTimer=new System.Timers.Timer(); 受保护的void start() { move(); aTimer.appead+=(源代码,e)=>move(); aTimer.AutoReset=true; aTimer.Enabled=!aTimer.Enabled; } 受保护的无效移动() { aTimer.间隔=1000.0/当前值; 位置=(位置+v); 如果(位置>500 | |位置nRenders++); }
      你也有一个每秒可以查看500次的用户吗?@HenkHolterman否我不:)我真的不想那么频繁地更新GUI。但是,只需连接到事件并调用StateHasChanged就很容易了。它是(有一点)收集多个事件并一起处理它们需要做更多的工作。因此,如果blazor已经执行了一些状态已更改的缓冲,我不需要重新实施我自己的策略。您是否也有一个每秒可以查看500次的用户?@Henkholtman否我不:)我真的不想那么频繁地更新GUI。但是,只需连接到事件并调用StateHasChanged就很容易了。它是(一点点)收集多个事件并一起处理它们需要做更多的工作。因此,如果blazor已经执行了一些StateHasChanged的缓冲,我不需要重新实现我自己的策略。hasPendingQueuedRender逻辑是这里最大的保证。查看渲染启动的频率仍然很有趣。不确定这个答案。有一个队列,但也有一种刷新队列的方法(例如在任务结束时)。如果每秒刷新队列500次会发生什么情况?队列用于将更改存储在非渲染块中(例如:任务内部)@daniherrera-此处的队列始终为@HenkHolterman的长度,您知道
      statehaschange
      不会强制渲染,只是标记了要渲染的组件。