Thread 初学(二)——线程同步

来源:互联网 发布:生理学题库软件 编辑:程序博客网 时间:2024/06/06 19:12
 

在讨论thread的常用方法之前,有必要先说一说IsBackground属性。废话少说上代码。

 1   private void Form1_Load(object sender, EventArgs e) 2         { 3             Thread t = new Thread(run); 4             t.Start(); 5             t.IsBackground=true; // 设置是否为后台线程 6         } 7         public void run() 8         { 9             while (true)10             {11                 Thread.Sleep(1000);12             }13         }

加注释代码是设置IsBackground属性,如果设置为true,当主线程结束的时候,此线程必然结束。如果设置成false或者是不设置(就是注释掉第五行代码),就为前台线程,当主线程结束时,他也不结束。任然运行着。

下面记录线程同步学习笔记

 

线程同步可以使用以下三个类进行管理Interlocked(互锁类)Monitor(管理类)

Mutex(互斥体),还有一个简单的方法就是Lock();

Interlocked中常用的方法:

根据方法介绍,很明显如果我们的程序中需要做到线程同步,就需要一个自定义的“计数器”

以下是代码作为一个简单的线程同步例子:

界面效果图

代码:

private static long numberOfusedSpace = 0;//计数器也是个控制量用于互锁        int lenth = 0;        private void button1_Click(object sender, EventArgs e)        {            if (button1.Text.Contains("开始"))            {                richTextBox1.ReadOnly = true;                textBox1.ReadOnly = true;                 richTextBox2.ReadOnly = true;                lenth = richTextBox1.Text.Trim().Length;                Thread threadReadPoolA = new Thread(ReadPoolA);                Thread threadWritePoolB = new Thread(WritePoolB);                threadReadPoolA.IsBackground = true;                threadWritePoolB.IsBackground = true;                threadReadPoolA.Start();                threadWritePoolB.Start();                button1.Text = "清空 重来";            }            else            {                richTextBox1.ReadOnly = false;                textBox1.ReadOnly = true;                richTextBox2.ReadOnly = false;                foreach (Control temp in this.Controls)                {                    if (temp.GetType().ToString().Contains("TextBox"))                    {                        temp.Text = "";                    }                }                button1.Text = "开始流动;            }        }        /// <summary>        ///读取池子中的数据,并将它写入到管道(计数器)中        /// </summary>        private void ReadPoolA()        {            UserControl.CheckForIllegalCrossThreadCalls = false;            string s = richTextBox1.Text.Trim();                        while (richTextBox1.Text.Trim().Length > 0)            {                while (Interlocked.Read(ref numberOfusedSpace) == 1)                {                    Thread.Sleep(300);                }                textBox1.Text = s[0].ToString();                Interlocked.Increment(ref numberOfusedSpace);                s = s.Substring(1);                richTextBox1.Text = s;                //Thread.Sleep(1000);            }        }        /// <summary>        /// 读取管道(计数器)中的数据,并将它写入到池子中        /// </summary>        private void WritePoolB()        {            UserControl.CheckForIllegalCrossThreadCalls = false;            while (richTextBox2.Text.Trim().Length < lenth)            {                while (Interlocked.Read(ref numberOfusedSpace) == 0)                {                    Thread.Sleep(300);                }                richTextBox2.AppendText(textBox1.Text);                textBox1.Text = "";                Interlocked.Decrement(ref numberOfusedSpace);                //Thread.Sleep(1000);            }        }

 

Monitor中常用的方法

 

根据上面的方法可以判断我们需要一个锁信号,一半情况下都是一个空的object类型。是不是可以设置其他类型呢?我们可以再以后空闲的时候尝试一下。

界面样式:

代码:

 1 private static object lockobj = new object();  //锁对象 2         int lenth = 0;                                // 长¡è度¨¨ 3         private void button1_Click(object sender, EventArgs e) 4         { 5             lenth = richTextBox1.Text.Trim().Length; 6             Thread threadReadPoolA = new Thread(ReadPoolA); 7             Thread threadWritePoolB = new Thread(WritePoolB); 8             threadReadPoolA.IsBackground = true; 9             threadWritePoolB.IsBackground = true;10             threadReadPoolA.Start();11             threadWritePoolB.Start();12         }13         private void ReadPoolA()14         {15             UserControl.CheckForIllegalCrossThreadCalls = false;16             string temp = richTextBox1.Text.Trim();17             while (richTextBox1.Text.Trim().Length > 0)18             {19                 try20                 {21                     Monitor.Enter(lockobj);    //进入所对象锁定对象22                     textBox1.Text = temp[0].ToString();23                     temp = temp.Substring(1);24                     richTextBox1.Text = temp;25                     Monitor.Pulse(lockobj);   //唤醒在所对象上蹲着的线程告诉他你可以执行了,锁对象的状态已更改。26                     Monitor.Wait(lockobj);    //释放锁对象,并且不让自己立刻就获取该对象,但是要等着再次获得对象才能往下执行27 28                 }29                 catch (ThreadInterruptedException ex)30                 {31 32                     MessageBox.Show(ex.ToString());33                 }34                 finally35                 {36                     Monitor.Exit(lockobj);37                 }38             }39         }40         private void WritePoolB()41         {42             UserControl.CheckForIllegalCrossThreadCalls = false;43             while (richTextBox2.Text.Trim().Length < lenth)44             {45                 try46                 {47                     Monitor.Enter(lockobj);48                     richTextBox2.AppendText(textBox1.Text);49                     textBox1.Text = "";50                     Monitor.Pulse(lockobj);51                     Monitor.Wait(lockobj);52                 }53                 catch (ThreadInterruptedException ex)54                 {55                     MessageBox.Show(ex.ToString());56                 }57                 finally58                 {59                     Monitor.Exit(lockobj);60                 }61             }62         }63 64         private void button2_Click(object sender, EventArgs e)65         {66             foreach (Control c in this.Controls)67             {68                 if (c.GetType().ToString().Contains("TextBox"))69                 {70                     c.Text = "";71                 }72             }73         }

 

Mutex常用的方法:

界面:

做个功能简单的说明,这个功能是实现同时向1.txt文件写数据。

代码:

 1 private void Form1_Load(object sender, EventArgs e) 2         { 3             System.Diagnostics.Process.Start("MetuxA.exe"); 4             Thread thread = new Thread(delegate() 5             { 6                 string filepat = @"e:\1.txt"; 7                 Mutex mt = new Mutex(false, "MutexRefObj"); 8                 while (true) 9                 {10                     try11                     {12                         mt.WaitOne();13                         if (!File.Exists(filepat))14                         {15                             File.Create(filepat);16                         }17                         string temp = "MetuxB: " + DateTime.Now.ToString() + "\r\n";18                         File.AppendAllText(filepat, temp);19                         Invoke(new EventHandler(delegate20                         {21                             richTextBox1.AppendText(temp);22                         }));23                     }24                     catch (ThreadInterruptedException ex)25                     {26                         MessageBox.Show(ex.ToString());27                     }28                     finally29                     {30                         mt.ReleaseMutex();31                     }32                     Thread.Sleep(500);33                 }34             });35             thread.IsBackground = true;36             thread.Start();37         }38     }39 40 41 A B两个类的代码几乎相同。

ps:在这里没有说明lock的使用方法,可能在明天或者是今天晚上我将温习一下lock和跨线程控件访问的控制。