使用WPF,是否有一种方法来检测阻止GUI更新的方法调用?

时间:2014-09-11 08:16:24

标签: wpf xaml asynchronous mvvm-light async-await

我想知道是否有一些技术或方法来检测WPF应用中没有使用async / await的呼叫。

我问的原因是我正在处理的WPF应用程序在屏幕更新上是口吃和停顿,我似乎无法追踪阻止GUI线程的调用源。

我正在使用VS2012和VS2013以及MVVM设计模式。

4 个答案:

答案 0 :(得分:6)

这不会直接回答您的问题,但这有助于识别调度程序线程何时重载,以下代码使用DispatcherInactive事件周围的事件处理程序来计算调度程序线程已经过载(阻止)的工作时间:

var maxThreshold = TimeSpan.FromMilliseconds(750);
var previous = DateTime.Now;

     Application.Current.MainWindow
        .Dispatcher.Hooks.DispatcherInactive += (sender, eventArgs) =>
        {
            var current = DateTime.Now;
            var delta = current - previous;

            previous = current;

            if (delta > maxThreshold)
            {
                Debug.WriteLine("UI Freeze = {0} ms", delta.TotalMilliseconds);
            }
         };

我建议这只用于调试模式,因此它将被包装在#if DEBUG块中。你不希望它在生产中运行。

答案 1 :(得分:1)

我认为在这种情况下performance profiler可以帮到你。 我个人推荐ANTS profiler,您可以下载试用版并使用它测试您的应用程序。它会告诉您应用程序执行的某段时间在哪里花费时间。

答案 2 :(得分:1)

通常很容易找到阻止UI的内容。可能有两种情况 - 您要么在UI线程上执行昂贵的操作,您可以测试执行的线程是否是使用的UI线程:

if (Thread.CurrentThread == Dispatcher.CurrentDispatcher.Thread)
{
    //UI Thread
}

或者,您正在显示许多控件,渲染需要很长时间。通常,当列表没有虚拟化项目时,列表会导致这种情况。

答案 3 :(得分:1)

您可以订阅WPF调度程序的事件来跟踪您的问题。 UI线程将名为Dispatcher的对象内的工作项排队。 Dispatcher优先选择工作项并运行每个工作项完成。

要监控Dispatcher,您可以例如订阅这些操作:

Dispatcher.Hooks.OperationPosted += Hooks_OperationPosted;
Dispatcher.Hooks.OperationStarted += Hooks_OperationStarted;
Dispatcher.Hooks.OperationAborted += Hooks_OperationAborted;

您可以找到完整列表here

根据您的问题,您可能会发现自己更适合使用商业分析器,但通常只需观察调度程序队列就可以获得良好的结果。