编写高质量代码C#建议72:在线程同步中使用信号量

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了编写高质量代码C#建议72:在线程同步中使用信号量相关的知识,希望对你有一定的参考价值。

1.使用信号机制提供线程同步的一个简单例子

        AutoResetEvent autoResetEvent = new AutoResetEvent(false);
        private void button1_Click(object sender, EventArgs e)
        {
            Control.CheckForIllegalCrossThreadCalls = false;
            Thread tWork = new Thread(() =>
            {
                label1.Text = "线程启动..." + Environment.NewLine;
                label1.Text += "开始处理一些实际的工作" + Environment.NewLine;
                //省略工作代码
                label1.Text += "我开始等待别的线程给我信号,才愿意继续下去" + Environment.NewLine;
                autoResetEvent.WaitOne();
                label1.Text += "我继续做一些工作,然后结束了!";
                //省略工作代码
            });
            tWork.IsBackground = true;
            tWork.Start();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            //将事件状态设置为终止状态,允许一个或多个等待线程继续
            autoResetEvent.Set();
        }

  以上例子中,点击按钮1执行到autoResetEvent.WaitOne()不再往下,点击按钮2才会继续往下执行。

2.AutoResetEvent和ManualResetEvent的区别:

使用AutoResetEvent,autoResetEvent.Set()只能使一个线程继续,而ManualResetEvent,manualResetEvent.Set()可使多个线程继续执行。

例子如下:

 

      private void button2_Click(object sender, EventArgs e)
        {
            //将事件状态设置为终止状态,允许一个或多个等待线程继续
            //autoResetEvent.Set();
            manualResetEvent.Set(); 
        }

        private void button3_Click(object sender, EventArgs e)
        {
            Control.CheckForIllegalCrossThreadCalls = false;
            StartThread1();
            StartThread2();
        }
        private void StartThread1()
        {
            Thread tWork1 = new Thread(() =>
            {
                label1.Text = "线程1启动..." + Environment.NewLine;
                label1.Text += "开始处理一些实际的工作" + Environment.NewLine;
                //省略工作代码
                label1.Text += "我开始等待别的线程给我信号,才愿意继续下去" + Environment.NewLine;
                //autoResetEvent.WaitOne();
                manualResetEvent.WaitOne();
                label1.Text += "我继续做一些工作,然后结束了!";
                //省略工作代码
            });
            tWork1.IsBackground = true;
            tWork1.Start();
        }

        private void StartThread2()
        {
            Thread tWork2 = new Thread(() =>
            {
                label2.Text = "线程2启动..." + Environment.NewLine;
                label2.Text += "开始处理一些实际的工作" + Environment.NewLine;
                //省略工作代码
                label2.Text += "我开始等待别的线程给我信号,才愿意继续下去" + Environment.NewLine;
                //autoResetEvent.WaitOne();
                manualResetEvent.WaitOne();
                label2.Text += "我继续做一些工作,然后结束了!";
                //省略工作代码
            });
            tWork2.IsBackground = true;
            tWork2.Start();
        }

3.模拟网络通信

        private void button4_Click(object sender, EventArgs e)
        {
            Control.CheckForIllegalCrossThreadCalls = false;
            Thread t = new Thread(() => {
                while (true)
                {
            //原理:没隔3秒检测接收,若未接收到a.Set(),则离线 bool re=a.WaitOne(3000); if (re) { label3.Text = string.Format("时间:{0},{1}", DateTime.Now.ToString(), "在线"); } else { label3.Text = string.Format("时间:{0},{1}", DateTime.Now.ToString(), "离线"); } } }); t.IsBackground = true; t.Start(); } private void button5_Click(object sender, EventArgs e) { a.Set(); }

  

以上是关于编写高质量代码C#建议72:在线程同步中使用信号量的主要内容,如果未能解决你的问题,请参考以下文章

编写高质量代码改善C#程序的157个建议——建议86:Parallel中的异常处理

编写高质量代码改善C#程序的157个建议——建议89:在并行方法体中谨慎使用锁

编写高质量代码C#建议71:区分异步和多线程应用场景

编写高质量代码改善C#程序的157个建议——建议74:警惕线程的IsBackground

编写高质量代码改善C#程序的157个建议——建议66:正确捕获多线程中的异常

编写高质量代码改善C#程序的157个建议——建议75:警惕线程不会立即启动