zoukankan      html  css  js  c++  java
  • WPF与Log4多线程UI死锁

    来,先看代码:

    public Launch()
    {
        Log4.LogEventHandler += Log4_LogEventHandler;
    
        InitializeComponent();
    }
    
    
    
    protected override void OnInitialized(EventArgs e)
    {
             Task.Run(() =>
              {
                    Task.Run(() =>
                    {
                        Thread.Sleep(1000);
    
                        Log4.Info("111");
                    });
    
                    Dispatcher.Invoke(() =>
                     {
                         Thread.Sleep(2000);
    
                         Log4.Info("222");
                     });
                });
    }
    
    
    
    void Log4_LogEventHandler(log4net.Core.LoggingEvent arg)
    {
        if (arg.Level == Level.Debug) return;
    
        Dispatcher.Invoke(() =>
        {
            _lbLog.Content = arg.RenderedMessage;
        });
    
    }

    如果在WPF主线程使用了这样多线程模型,你的UI线程有可能卡死,当然,这里也与我使用的 Log4 有关。

    注意:每次调用 Log4.Info("xxx"), Log4_LogEventHandler 必被调用,它只是 Log 的一个回调函数。

    注意,这里就是关键点!!!

    OnInitialized 方法里我开启了二级线程,并在一级线程调用了 Dispatcher.Invoke,这个方法是同步的。

    1、Thread.Sleep(1000) 是为了模拟先让一级线程调用 Dispatcher.Invoke,但内部 Sleep 了2000,此时二级线程已经开启。

    2、Thread.Sleep(2000) 是为了先让让二级线程调用 Log4.Info("111"),然后导致 Log4_LogEventHandler 函数被执行,间接调用了 Dispatcher.Invoke 方法,但此时线程会被 Hold 住(但这里Hold 住的并不是 UI 线程而是二级线程,此时 UI 线程还是正常的),因为一级线程的 Dispatcher.Invoke 方法还没有执行完成,因为在上述步骤时,一级线程抢先占用了  Dispatcher.Invoke。

    3、Thread.Sleep(2000)  完成,继续调用 Log4.Info("222"),这里就是问题了,可能是因为 Log4 的机制问题,每次调用 Log 方法必须上次调用完成后,才能继续执行下一个 Log 方法,因为二级线程的 Log4.Info("111") 方法并没有完成,而是被 Hold 了,一级线程又去  Log4.Info("222"),导致线程又被 Hold ,此时被 Hold 的线程是 UI 线程,最后导致 UI 线程卡死。

    完美造成了死锁!!!

    解决方案:

    建议使用 Dispatcher.BeginInvoke 方法,这个方法是异步的,并不会 Holde 线程。但如果你又有同步需求,这时你就需要时刻注意避免形成上诉的线程模型。这个死锁原因花了我大半天的时间才解开,藏的太深了。

  • 相关阅读:
    VC6 下 libpng 库的编译与初步使用
    Windows上编译libtiff
    ActiveX控件开发
    静态库和动态库的优缺点
    KStudio window上编译uclinux
    4. API之打印函数
    window消息机制二
    消息机制、子窗口和父窗口的消息传递
    window消息机制
    dll 显示调用
  • 原文地址:https://www.cnblogs.com/yuys/p/12049755.html
Copyright © 2011-2022 走看看