Determine what is blocking UI thread

2020-06-03 04:26发布

I am working on a rather large .NET WPF real-time application. The application is working great and as expected, except for one BIG issue - UI Update is slow.

This application is highly event driven, there are events raised all over for all sorts of things - through these events the UI is updated.

One or many of these events is blocking the UI from displaying immediately. When all the work is complete, the UI shows the expected results.

Is there any way of determining which event handler is causing the bottleneck?

Any help would be appreciated.

4条回答
再贱就再见
2楼-- · 2020-06-03 04:57

As a first order approxximation, I find it useful to break in the debugger (with the pause button in the IDE), and look at the stack. Do this a few times, and you can see if there is a pattern. Are you always in the same function? Are you doing something expensive in response to an event? Are you getting more events that you expect? It's low tech, but can be very effective.

查看更多
乱世女痞
3楼-- · 2020-06-03 05:08

Do you have access to a code profiler? This is the type of thing they are good at. I recommend obtaining one if the answer is no.

Besides using a profiler. You can do "poor man's" profiling by placing timing statements at the beginning and end of code blocks that you suspect. You can even use a breakpoints and time it with a wall clock. Does the issue happen when you click something? If so start there. Is it a recurring issue without user interaction? Start with timers then.

As for actually solving the problem... Unless the offending handler is doing something that can be made more efficient, consider adopting a multi-threaded approach. The new Task library for .NET 4.0 is really amazing in this regard.

查看更多
▲ chillily
4楼-- · 2020-06-03 05:11

I fully support colithium's suggestion of using a profiler.

In addition, if the blocking takes more than a second, you might be able to hit the "Pause" button in Visual Studio. In the tool bar, there's a dropdown list where you can choose the "Main Thread". Then it jumps to the method which is currently blocking the UI.

查看更多
孤傲高冷的网名
5楼-- · 2020-06-03 05:18
  public class UIBlockDetector
{
    static Timer _timer;
    public UIBlockDetector(int  maxFreezeTimeInMilliseconds = 200)
    {
        var sw = new Stopwatch();

        new DispatcherTimer(TimeSpan.FromMilliseconds(10), DispatcherPriority.Send, (sender, args) =>
        {
            lock (sw)
            {
                sw.Restart();
            }

        }, Application.Current.Dispatcher);

        _timer = new Timer(state =>
        {
            lock (sw)
            {
                if (sw.ElapsedMilliseconds > maxFreezeTimeInMilliseconds)
                {
                    // Debugger.Break() or set breakpoint here;
                    // Goto Visual Studio --> Debug --> Windows --> Theads 
                    // and checkup where the MainThread is.
                }
            }

        }, null, TimeSpan.FromMilliseconds(0), TimeSpan.FromMilliseconds(10));

    }

}

Just new this class in MainWindow constructor. When the breakpoint hits, you can go to Visual Studio --> Debug --> Windows --> Threads and check what operation blocked your UI-Thread!

查看更多
登录 后发表回答