none
wpf线程同步问题 RRS feed

  • 问题

  • 现在想实现一个功能,双击鼠标后开始工作,实现以下的输出顺序:

    主线程开始 0   1  2 ---- 29 主线程结束。

    但是,现在下面的代码输出 主线程开始 0 1 2 ---9 (主线程结束 10--19 20--29 这三个输出顺序不定)

    现在加上一个AutoResetEvent,将richTextBox.Dispatcher.Invoke改为richTextBox.Dispatcher.BeginInvoke可以实现原来的需求,但是还是会阻塞UI线程,求问如何改可以实现不阻塞UI线程?

        public partial class Window1 : Window
        {
            public Window1()
            {
                InitializeComponent();
            }
    
            private void richTextBox_MouseDoubleClick(object sender, MouseButtonEventArgs e)
            {
                richTextBox.AppendText( "主线程开始"+"\r\n");
                DoWork dowork=new DoWork(richTextBox);
                dowork.Start();
                richTextBox.AppendText( "主线程结束"+"\r\n");
            }
        }
        public class DoWork
        {
            public DoWork(RichTextBox r) { richTextBox = r; }
            private RichTextBox richTextBox;
            private System.ComponentModel.BackgroundWorker worker = new System.ComponentModel.BackgroundWorker();
            private AutoResetEvent autoResetEvent = new AutoResetEvent(false);
            public void Start()
            {
                worker.DoWork += new System.ComponentModel.DoWorkEventHandler(worker_DoWork);
                worker.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
                for (int i = 0; i < 10; i++)
                {
                    Action action=()=>richTextBox.AppendText( i.ToString()+"\r\n");
                    richTextBox.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, action);
                }
                worker.RunWorkerAsync();
                //autoResetEvent.WaitOne();
            }
    
            void worker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
            {
                //throw new NotImplementedException();
                for (int i = 20; i < 30; i++)
                {
                    Action action = () => richTextBox.AppendText( i.ToString() + "\r\n");
                    richTextBox.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, action);
                }
                //autoResetEvent.Set();
            }
    
            void worker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
            {
                //throw new NotImplementedException();
                for (int i = 10; i < 20; i++)
                {
                    Action action = () => richTextBox.AppendText( i.ToString() + "\r\n");
                    richTextBox.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, action);
                }
            }
        }

    2012年8月19日 13:42

答案

  • 在不使用AutoResetEvent(我不了解这个事件)情况下,初步看上去,在你的代码逻辑上,输出的顺序是:

    "主线程开始" -> 1~9 -> "主线程结束" -> 10~19 -> 20~29

    你应当在RunWorkerCompleted事件中处理线程结束的通知。

    在不新建线程的前提下,必然会导致线程阻塞,你可以新建线程解决该问题。


    Wanpeng wanpeng.ones@gmail.com

    • 已标记为答案 cuso4sean 2012年8月27日 13:01
    2012年8月20日 8:48