C# Winform 界面线程的Invoke死锁,以及Application.DoEvent的问题

1.对于非界面线程来说,Invoke是把一个操作丢到界面线程的队列里,然后阻塞,等到这个操作被界面线程完成后,才继续后续操作。也就是说,Invoke是同步的。

    问题来了,如果界面线程此时正在等待这个非界面线程的结束,然而这个非界面线程却又在等待界面线程执行完这个Invoke操作时,就会发生死锁。

2.说白了,这个死锁问题,是Invoke执行机制产生的。

3.解开这个死锁的方案也很简单。对于Invoke逻辑没有与界面线程逻辑有任何关系,则可以直接改造界面线程的等待非界面线程的结束操作:

    function ThreadUI()

    {

        while(true)

        {

               if( Thread_New.ThreadState == Stopped )

               {

                      break;

               }

               else

               {

                      Sleep(10);

               }

        }

    }

    改造成:

    function ThreadUI()

    {

        while(true)

        {

               if( Thread_New.ThreadState == Stopped )

               {

                      break;

               }

               else

               {

                      Sleep(10);

                      Application.DoEvent();//这个语句,会让UI线程处理Invoke队列里的事情

               }

        }

    }

   如果Invoke逻辑与界面线程的逻辑,有互相调用甚至加锁的关系,则需要先画图理清楚关系,然后再重新改造整个逻辑。此时,可能需要几个技术来辅助操作:

    1.新增线程或队列来分解事务

    2.把一些同步方法,改造成异步方法。改造成异步方法后,需要注意gc问题,以及错误处理问题。

    3.把一个大任务,按照执行顺序,分解为多个子任务,依次执行。

原文地址:https://www.cnblogs.com/xxxteam/p/3181203.html