【问题标题】:Querying the Dispatcher Queue Length查询 Dispatcher 队列长度
【发布时间】:2021-06-08 12:04:32
【问题描述】:

我正在尝试分析 UI 线程的使用情况。是否可以查询调度员排队的物品数量?

更新:克莱门斯的回答完美无缺,但是因为我想在 UI 启动后启动它并且我只关心每秒对数据进行一次采样,所以我使用以下代码...

        int queueLength = 0;
        var currentDispatcher = Dispatcher.CurrentDispatcher;
        currentDispatcher.Hooks.OperationPosted += (s, e) => Interlocked.Increment(ref queueLength);
        currentDispatcher.Hooks.OperationCompleted += (s, e) => Interlocked.Decrement(ref queueLength);
        currentDispatcher.Hooks.OperationAborted += (s, e) => Interlocked.Decrement(ref queueLength);
        Observable
            .Interval(TimeSpan.FromSeconds(1))
            .Subscribe(x =>
                           {
                               int currentQueueLength = queueLength;
                               if (currentQueueLength < 0)
                               {
                                   Interlocked.Add(ref queueLength, currentQueueLength * -1);
                               }
                               UiQueueLength = queueLength;
                           });

【问题讨论】:

    标签: wpf


    【解决方案1】:

    Afaik 没有可以直接询问调度程序队列长度的属性或方法。但是,您可以将处理程序附加到由Hooks 属性提供的一些DispatcherHooks 事件。

    var queueLength = 0;
    Dispatcher.Hooks.OperationPosted += (o, e) => Interlocked.Increment(ref queueLength);
    Dispatcher.Hooks.OperationStarted += (o, e) => Interlocked.Decrement(ref queueLength);
    Dispatcher.Hooks.OperationAborted += (o, e) => Interlocked.Decrement(ref queueLength);
    

    如果您只对 Dispatcher 是否处于活动状态感兴趣,您可以只处理 OperationPosted 事件和 DispatcherInactive

    【讨论】:

      【解决方案2】:

      l感谢以上,这里有一个类来完成这项工作:

      /*
       This is for when you want to know the depth of the Dispatcher Queue an perhaps modifiy the behaviour of
       code to minimize impact like when data is comming into a TextBox faster that it can cope with.
        
       Usage:
       in MainWindow
       public DispatcherQueueLength dispatcherQueueLengthHelper;
       dispatcherQueueLengthHelper = new DispatcherQueueLength(App.Current.Dispatcher);
       dispatcherQueueLengthHelper.StartDispatcherHooks();
       in Loaded
       dispatcherQueueLengthHelper.StartUpdateTimer(new TimeSpan(0,0,0,1,0), DispatcherPriority.Send, () =>
          {
                App.mainVM.LblQueueCountContent = "UI Queue Count ~ " + dispatcherQueueLengthHelper.GetQueueLength.ToString("N0");
          });
       in Closing
       dispatcherQueueLengthHelper.EndDispatcherHooks();
       dispatcherQueueLengthHelper.EndUpdateTimer();
      */
      
      public class DispatcherQueueLength
      {
          private static int _queueLenth = 0;
          private Dispatcher _dispatcher = null;
          private DispatcherTimer _dispatcherTimer = null;
      
          /// <summary>
          /// Usually pass in App.Current.Dispatcher
          /// </summary>
          /// <param name="passedDispatcher"></param>
          public DispatcherQueueLength(Dispatcher passedDispatcher)
          {
              _dispatcher = passedDispatcher;
      
          }
      
          
          /// <summary>
          /// Call as needed. It is possible to have a negative number like when pending Dispatches exist
          /// when starting the class, they are zeroed out.
          /// </summary>
          public int GetQueueLength
          {
              get 
              {
                  int currentQueueLength = _queueLenth;
                  if (currentQueueLength < 0)
                  {
                      Interlocked.Add(ref _queueLenth, currentQueueLength * -1); //this zeros it
                  }
      
                  return currentQueueLength;
              }
          }
      
      
          /// <summary>
          /// Call directly after instantiating the class
          /// </summary>
          public void StartDispatcherHooks()
          {
              if (_dispatcher != null)
              {
                  _dispatcher.Hooks.OperationPosted += (s, e) =>
                  {
                      Interlocked.Increment(ref _queueLenth);
                      Debug.WriteLine("Queue Length: " + _queueLenth.ToString());
                  };
                  _dispatcher.Hooks.OperationCompleted += (s, e) =>
                  {
                      Interlocked.Decrement(ref _queueLenth);
                  };
                  _dispatcher.Hooks.OperationAborted += (s, e) =>
                  {
                      Interlocked.Decrement(ref _queueLenth);
                  };
              }
          }
      
          /// <summary>
          /// You pass in the code you want run on each interval
          /// </summary>
          /// <param name="ts"></param>
          /// <param name="priority"></param>
          /// <param name="action"></param>
          public void StartUpdateTimer(TimeSpan ts, DispatcherPriority priority, Action action)
          {
              if(_dispatcherTimer == null)
              {
                  _dispatcherTimer = new DispatcherTimer(priority);
                  _dispatcherTimer.Tick += (s,e) => { action(); };
                  _dispatcherTimer.Interval = ts;
                  _dispatcherTimer.IsEnabled = true;
              }
      
          }
      
          /// <summary>
          /// Call in MainWindow Closing
          /// </summary>
          public void EndDispatcherHooks()
          {
              if(_dispatcher != null)
              {
                  _dispatcher.Hooks.OperationPosted -= (s, e) => Interlocked.Increment(ref _queueLenth);
                  _dispatcher.Hooks.OperationCompleted -= (s, e) => Interlocked.Decrement(ref _queueLenth);
                  _dispatcher.Hooks.OperationAborted -= (s, e) => Interlocked.Decrement(ref _queueLenth);
              }
             
          }
      
          //Call in MainWindow Closing or if no longer needed
          public void EndUpdateTimer()
          {
              _dispatcherTimer.Stop();
              _dispatcher = null;
      
          }
      
      
      }
      

      【讨论】:

        猜你喜欢
        • 2017-10-18
        • 1970-01-01
        • 2014-07-01
        • 1970-01-01
        • 2015-09-30
        • 2010-10-02
        • 2012-09-14
        • 2014-10-27
        • 1970-01-01
        相关资源
        最近更新 更多