在讨论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 = "开始流动; } } //////读取池子中的数据,并将它写入到管道(计数器)中 /// 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); } } ////// 读取管道(计数器)中的数据,并将它写入到池子中 /// 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和跨线程控件访问的控制。