AutoResetEvent waiter = new AutoResetEvent(false);在某个事件中写
waiter.Set();
然后整个界面就卡死了。在回调函数中写((AutoResetEvent)e.UserState).Set();也恢复不过来求解

解决方案 »

  1.   

    多线程编程尽量不要使用阻塞操作,用在主线程中胡写 WaitOne 等阻塞操作更是不行的。应该总是使用异步操作的概念来编程,这需要从脑筋上去对知识进行更新,而不要总是使用并行操作的语法来模拟顺序操作。如果实在是没有现成的异步操作方法可调用,那么你的主线程要开始一个操作时可以写类似
    http://msdn.microsoft.com/zh-cn/library/kbf0f1ct(v=vs.100).aspx
    这样的代码,也就是说你的主线程根本不阻塞。
      

  2.   

    我给你写两个代码,首先在一个窗体上拖入一个TextBox、一个Button、一个Label空间,然后试试代码:其一using System;
    using System.Threading;
    using System.Windows.Forms;namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            ManualResetEvent eh = new ManualResetEvent(false);        public Form1()
            {
                InitializeComponent();
            }        private void a()
            {
                Thread.Sleep(10000);
                this.label1.BeginInvoke(new Action(() => this.label1.Text = DateTime.Now.ToString() + "刷新了界面!"));
                eh.Set();
            }        private void button1_Click(object sender, EventArgs e)
            {
                a();
                eh.WaitOne();
            }
        }
    }
    其二using System;
    using System.Threading;
    using System.Windows.Forms;namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }        private void a()
            {
                Thread.Sleep(10000);
                this.label1.BeginInvoke(new Action(() => this.label1.Text = DateTime.Now.ToString() + "刷新了界面!"));
            }        private void button1_Click(object sender, EventArgs e)
            {
                ThreadPool.QueueUserWorkItem(h => a());
            }
        }
    }你可以看到第二种才不会阻塞界面上需要立刻响应的操作。第一种使用阻塞,虽然貌似是多线程编程,但是却失去了意义!
      

  3.   

    至于你在主线程中先WaitOne阻塞,然后在主线程中妄图调用Set,这更不用说自然是极其低级的编程错误。这种错误都懒得去当作一个什么设计模式去谈论啦。我给你写第三个程序using System;
    using System.Threading;
    using System.Windows.Forms;namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }        private void a(Action callback)
            {
                Thread.Sleep(5000);
                this.label1.BeginInvoke(new Action(() =>
                {
                    this.label1.Text = DateTime.Now.ToShortTimeString() + "第一次!";
                    if (callback != null)
                        callback();
                }));
            }        private void button1_Click(object sender, EventArgs e)
            {
                ThreadPool.QueueUserWorkItem(h => a(b));
            }        private void b()
            {
                Thread.Sleep(10000);
                this.label1.Text += "另一个程序被调用!";
            }
        }
    }
    你可以看到虽然我们把b给a让它处理完线程任务之后立刻继续调用b,但是此时主线程又被阻塞了。凡是滥用阻塞的程序都很容易失去多线程编程的意义!