zoukankan      html  css  js  c++  java
  • Thread 初学(二)——线程同步

    在讨论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                 try
    20                 {
    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                 finally
    35                 {
    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                 try
    46                 {
    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                 finally
    58                 {
    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                     try
    11                     {
    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(delegate
    20                         {
    21                             richTextBox1.AppendText(temp);
    22                         }));
    23                     }
    24                     catch (ThreadInterruptedException ex)
    25                     {
    26                         MessageBox.Show(ex.ToString());
    27                     }
    28                     finally
    29                     {
    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和跨线程控件访问的控制。

     

  • 相关阅读:
    springboot
    POI/JFreeChart
    ssm(6)spring-test
    DBUtils与BeanUtils
    数据连接池C3P0/DBCP/DRUID/自定义连接池
    web核心(3)响应头请求头状态码及dns解析过程
    log4j/Logback/SLF4j
    ssm(4)整合
    列表字典元组方法
    第四天 Python基础语法 编码规范 变量
  • 原文地址:https://www.cnblogs.com/xiaoch/p/2574163.html
Copyright © 2011-2022 走看看