Invoke阻塞的问题

我自定义了一个事件用来更新画面的进度条。
程序结构是子线程完成时触发事件,主线程(UI线程)订阅该事件做出响应。
现在的问题是,由于子线程完成的只是业务操作的一个步骤,所以我用join()阻塞了UI线程,而事件更新进度条看起来又是在子线程里完成的,触发了事件委托的Invoke的代码段,造成主线程等待子线程完成,而子线程又等待主线程完成的死锁状态,请问这个要怎么解决?

  • 事件类代码

    public class ProgressChangeEventPublisher
    {
            public event EventHandler<ProgressChangeEventArgs> RaiseProgressChangeEvent;
    
            private void OnRaiseProgressChangeEvent(ProgressChangeEventArgs e)
            {
                RaiseProgressChangeEvent?.Invoke(null, e);
            }
            public void ProgressChange(ProgressChangeEventArgs e)
            {
                OnRaiseProgressChangeEvent(e);
            }
    }
  • 事件触发

    class subclass{
        public ProgressChangeEventPublisher publisher = new ProgressChangeEventPublisher();
        //子线程方法
        private void threadmethod(object obj)
        {
            //用Semaphore对象控制线程并发数。
            semahoro.WaitOne();
            //激发事件
            pub.ProgressChange( new ProgressChangeEventArgs());
            
            semahoro.Release();
        }
        
        //创建启动线程
        void do()
        {
             List<Thread> tPool = new List<Thread>();
             foreach (var src in paths)
             {
                 Thread t = new Thread(new ParameterizedThreadStart(threadmethod));
                 t.Start(src);
                 tPool.Add(t);
             }
             foreach (Thread t in tPool)
             {
                t.Join();
             }
        }
    }
  • UI订阅代码

    delegate void ChangeStatusBarHandler(int progress, string status);
    
    private void btn_Click(object sender, EventArgs e)
    {
        subclass cls = new subclass();
        //实现事件订阅
        cls.publisher.RaiseProgressChangeEvent += OnProgressChange;
    }
    
    //事件委托
    void OnProgressChange(object sender, ProgressChangeEventArgs e)
    {
        if (e != null)
        {
            DoChangeStatusBar(e.percent, e.status_msg);
        }
    }
    
    void DoChangeStatusBar(int progress, string status) 
    {
        if (InvokeRequired)
        {
            Invoke(new ChangeStatusBarHandler(DoChangeStatusBar), new object[] { e.percent, e.status_msg });
        }
        else
        {
            tlPrgsBar.Value = progress;
        }
    }

    使用task启动线程的代码

    List<Task> tasks = new List<Task>();
    foreach (var src in paths)
    {    
       tasks.Add(Task.Factory.StartNew(threadRunParse,src));
    }
    Task.WaitAll(tasks.ToArray());
阅读 5.4k
1 个回答

Invoke改成BeginInvoke试试

既然这样,试试这个吧:

Task task=Task.Factory.Start(()=>{Invoke(/*噼里啪啦的事情*/);});
Application.DoEvent();
Task.WaitAll(task);

你问题的根源在于,你把主线程阻塞了,试问,主线程为什么要阻塞呢?
如果非要主线程等待执行结束后再执行一些事情,完全可以换种方式,比如做个进度完成的事件,主线程订阅后继续执行。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
logo
Microsoft
子站问答
访问
宣传栏