C# 多线程(学习笔记13)

1.进程与线程

进程是资源管理的最小单位,有自己的内存空间,一个进程可以有多个线程,各线程之间共享进程的系统资源。
多线程的意义在于多任务的并发执行。多线程对于自动化领域意义重大,例如一个线程去访问硬件设备读写数据,另一个线程需要操作数据库,
如果放在同一个线程中,那么就会造成程序的严重卡顿。

2.简单示例

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection.Emit;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WinFormC10
{
    public partial class Form1 : Form
    {
        private delegate void FlushClient();//代理
        int num = 0;
        public Form1()
        {
            InitializeComponent();
            // 禁止跨线程检查
            // Control.CheckForIllegalCrossThreadCalls = false;
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }



        private void Button1_Click(object sender, EventArgs e)
        {
            Thread thread = new Thread(M)
            {
                IsBackground = true
            };
            thread.Start();
        }


        private void M()
        {
            while (true)
            {
                S();
                Thread.Sleep(1000);
            }
        }
        private void S()
        {
            if (this.InvokeRequired)//等待异步
            {
                num++;
                FlushClient fc = new FlushClient(S);
                this.Invoke(fc);//通过代理调用刷新方法
            }
            else
            {
                this.Text = num.ToString();
            }

        }
    }

}

3. Thread类

3.1 属性

序号 属性 作用
1 IsBackground 是否是后台线程。后台线程会在前台线程结束后自动终止。
2 IsAlive 线程是否活动,false表示终止。
3 Priority 线程优先级
4 ThreadState 获得当前的线程状态
5 Name 线程名称
6 ManagedThreadId 当前线程ID

3.2 方法

序号 方法 作用
1 Sleep 休眠,线程挂起
2 Abort 终止(释放)。
3 Start 启动

Thread类属于比较旧版本的线程类,一般在.Net Frmaework3.5以下版本使用。

4. ThreadPool

每个进程只有一个线程池,线程池的线程都是后台线程。

  • 有点

作为后台线程运行;
线程执行时间较短;
默认优先级运行,无需设置优先级。
线程状态无须监控;

using System;
using System.Threading;

namespace ThreadPoolTest;
public class Program
{
    public static int count = 1000;
    public static void DoWork(object s)
    {
        for (int i = 0; i < count; i++)
        {
            Console.Write(s);
        }
    }

    public static void Main(string[] args)
    {

        ThreadPool.QueueUserWorkItem(DoWork, "+");
        ThreadPool.QueueUserWorkItem(DoWork, "=");

        for (int i = 0; i < count; i++)
        {
            Console.Write("-");
        }
        Thread.Sleep(100000);
    }
}

获得最小线程数:ThreadPool.GetMinThreads
获得最大线程数:ThreadPool.GetMaxThreads

  • 缺点

不知道线程状态( 不支持线程的取消,完成、失败通知等)。
不支持线程执行的先后顺序。
对长时间执行的线程没有后台优化。

5. Task

基于任务的异步编程模型,性能和易用性得到进一步提升。
由ThreadPool来执行和回收。
Task执行完成后,不能再回到创建处。

5.1 基本用法

using System;
using System.Runtime.ExceptionServices;
using System.Threading.Tasks;

namespace TaskTest01

{
    class Program

    {
        private const int CNT = 1000000;
        private volatile static bool flag = false;
        static void Main(string[] args)
        {

            Task task01 = Task.Run(() =>
              {
                  for (int i = 0; i < CNT; i++)
                  {
                      if (flag)
                      {
                          Console.Write("\r\n");
                          break;
                      }
                      Console.Write("...");
                      Thread.Sleep(50);
                  }

              });

            while (true)
            {
                // 查询 task1的状态
                if (task01.IsCompleted)
                {
                    Console.WriteLine("Task task01 is Completed!");
                    break;
                }
                // 输入q会退出
                var q = Console.ReadKey().KeyChar;
                if (q == 'q')
                {
                    flag = true;
                }
            }
            Console.ReadKey();
        }

        private static void n()
        {
            for (int i = 0; i < CNT; i++)
            {
                Console.Write("-");
            }
        }
    }
}

5.2 耗时任务分配专用线程

using System;
using System.Runtime.ExceptionServices;
using System.Threading.Tasks;

namespace TaskTest01

{
    class Program2

    {
        private const int CNT = 1000000;
        private volatile static bool flag = false;
        static void Main(string[] args)
        {
            // 分配专用线程处理
            Task task01 = new Task(n, TaskCreationOptions.LongRunning);
            task01.Start();
            while (true)
            {
                if (task01.IsCompleted)
                {
                    Console.WriteLine("Task task01 is Completed!");
                    break;
                }
                // 输入q会退出
                var q = Console.ReadKey().KeyChar;
                if (q == 'q')
                {
                    flag = true;
                }
            }
            Console.ReadKey();
        }

        private static void n()
        {
            for (int i = 0; i < CNT; i++)
            {
                if (flag)
                {
                    Console.Write("\r\n");
                    break;
                }
                Console.Write("...");
                Thread.Sleep(50);
            }
        }
    }
}

6. async/await

async/await在C#5.0引入,使得异步编程更加容易。
一般用于耗时较长的操作。
async/await 是对task的进一步封装。
async和await 一般是成对出现的。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WinFormC10
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }

        private async void Button1_Click(object sender, EventArgs e)
        {
            // 等待Calc的结果
            string s = await Calc();
            textBox1.Text = s;
            textBox1.BackColor = Color.Red;
        }

        /// <summary>
        /// 异步执行Calc
        /// </summary>
        /// <returns></returns>
        private Task<string> Calc()
        {
            string tid = Thread.CurrentThread.ManagedThreadId.ToString();
            string s = "";
            return Task.Run(() =>
            {
                for (int i = 1; i <= 9999999; i++)
                {
                    s = i.ToString();
                }
                return tid + "   " + s;
            });
        }
    }
}
posted @ 2025-11-25 17:22  huiy_小溪  阅读(6)  评论(0)    收藏  举报