C# 创建线程的方式

在C#里,创建线程有多种方式,下面为你详细介绍并给出示例。

1. 使用Thread类

通过Thread类创建线程是最基础的方式,有两种途径可以启动线程:

  • 使用ThreadStart委托:这种方式适用于线程执行的方法没有返回值(即返回类型为void)。
  • 使用ParameterizedThreadStart委托:当线程执行的方法需要参数时,可以使用这种方式。

下面是具体的示例代码:

using System;
using System.Threading;

class Program
{
    static void Main()
    {
        // 使用ThreadStart委托
        Thread thread1 = new Thread(PrintNumbers);
        thread1.Start();

        // 使用ParameterizedThreadStart委托
        Thread thread2 = new Thread(PrintNumbersWithDelay);
        thread2.Start(500); // 传递毫秒级延迟作为参数

        Console.WriteLine("主线程继续执行...");
        Console.ReadLine();
    }

    static void PrintNumbers()
    {
        for (int i = 1; i <= 5; i++)
        {
            Console.WriteLine($"线程1: {i}");
            Thread.Sleep(100);
        }
    }

    static void PrintNumbersWithDelay(object delay)
    {
        int ms = (int)delay;
        for (int i = 1; i <= 5; i++)
        {
            Console.WriteLine($"线程2: {i}");
            Thread.Sleep(ms);
        }
    }
}

2. 使用ThreadPool

线程池能够管理和复用线程,从而减少线程创建和销毁所带来的开销。你可以使用QueueUserWorkItem方法将工作项加入线程池队列。

using System;
using System.Threading;

class Program
{
    static void Main()
    {
        // 将方法排入线程池队列执行
        ThreadPool.QueueUserWorkItem(PrintNumbers);
        ThreadPool.QueueUserWorkItem(PrintNumbersWithDelay, 300);

        Console.WriteLine("主线程继续执行...");
        Console.ReadLine();
    }

    static void PrintNumbers(object state)
    {
        for (int i = 1; i <= 5; i++)
        {
            Console.WriteLine($"线程池线程: {i}");
            Thread.Sleep(100);
        }
    }

    static void PrintNumbersWithDelay(object delay)
    {
        int ms = (int)delay;
        for (int i = 1; i <= 5; i++)
        {
            Console.WriteLine($"带延迟的线程池线程: {i}");
            Thread.Sleep(ms);
        }
    }
}

3. 使用Task Parallel Library (TPL)

借助Task类可以创建和管理异步操作,这是.NET 4.0引入的特性,推荐优先使用这种方式。

using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static void Main()
    {
        // 使用Task.Factory.StartNew
        Task task1 = Task.Factory.StartNew(PrintNumbers);

        // 使用Task.Run (简化版)
        Task task2 = Task.Run(() => PrintNumbersWithDelay(400));

        // 带返回值的任务
        Task<int> task3 = Task.Run(() => CalculateSum(10));
        Console.WriteLine($"计算结果: {task3.Result}");

        Console.WriteLine("主线程继续执行...");
        Task.WaitAll(task1, task2); // 等待所有任务完成
        Console.ReadLine();
    }

    static void PrintNumbers()
    {
        for (int i = 1; i <= 5; i++)
        {
            Console.WriteLine($"任务1: {i}");
            Thread.Sleep(100);
        }
    }

    static void PrintNumbersWithDelay(int delay)
    {
        for (int i = 1; i <= 5; i++)
        {
            Console.WriteLine($"任务2: {i}");
            Thread.Sleep(delay);
        }
    }

    static int CalculateSum(int n)
    {
        int sum = 0;
        for (int i = 1; i <= n; i++)
        {
            sum += i;
            Thread.Sleep(50);
        }
        return sum;
    }
}

4. 使用async/await关键字

asyncawait关键字是.NET 4.5引入的语法糖,它基于TPL构建,能够让异步代码看起来更像同步代码。

using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        Console.WriteLine("主线程开始...");

        // 启动异步任务
        Task task1 = PrintNumbersAsync();
        Task<int> task2 = CalculateSumAsync(15);

        // 等待任务完成
        await task1;
        Console.WriteLine($"计算结果: {await task2}");

        Console.WriteLine("主线程结束.");
        Console.ReadLine();
    }

    static async Task PrintNumbersAsync()
    {
        await Task.Run(() =>
        {
            for (int i = 1; i <= 5; i++)
            {
                Console.WriteLine($"异步任务: {i}");
                Thread.Sleep(200);
            }
        });
    }

    static async Task<int> CalculateSumAsync(int n)
    {
        return await Task.Run(() =>
        {
            int sum = 0;
            for (int i = 1; i <= n; i++)
            {
                sum += i;
                Thread.Sleep(100);
            }
            return sum;
        });
    }
}

5. 使用BackgroundWorker组件(Windows Forms/WPF环境)

在Windows Forms或WPF应用程序中,可以使用BackgroundWorker组件来执行后台操作,并且能够与UI线程进行安全通信。

using System;
using System.ComponentModel;
using System.Threading;
using System.Windows.Forms;

namespace BackgroundWorkerExample
{
    public partial class Form1 : Form
    {
        private BackgroundWorker backgroundWorker1;

        public Form1()
        {
            InitializeComponent();

            // 初始化BackgroundWorker
            backgroundWorker1 = new BackgroundWorker();
            backgroundWorker1.DoWork += BackgroundWorker1_DoWork;
            backgroundWorker1.ProgressChanged += BackgroundWorker1_ProgressChanged;
            backgroundWorker1.RunWorkerCompleted += BackgroundWorker1_RunWorkerCompleted;
            backgroundWorker1.WorkerReportsProgress = true;
            backgroundWorker1.WorkerSupportsCancellation = true;
        }

        private void buttonStart_Click(object sender, EventArgs e)
        {
            if (!backgroundWorker1.IsBusy)
            {
                backgroundWorker1.RunWorkerAsync(10); // 传递参数
            }
        }

        private void buttonCancel_Click(object sender, EventArgs e)
        {
            if (backgroundWorker1.WorkerSupportsCancellation)
            {
                backgroundWorker1.CancelAsync();
            }
        }

        private void BackgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;
            int max = (int)e.Argument;

            for (int i = 1; i <= max; i++)
            {
                if (worker.CancellationPending)
                {
                    e.Cancel = true;
                    break;
                }
                else
                {
                    // 执行工作
                    Thread.Sleep(500);
                    worker.ReportProgress(i * 10);
                }
            }

            e.Result = max;
        }

        private void BackgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            // 更新UI(安全操作)
            progressBar1.Value = e.ProgressPercentage;
            labelStatus.Text = $"完成 {e.ProgressPercentage}%";
        }

        private void BackgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled)
            {
                labelStatus.Text = "操作已取消";
            }
            else if (e.Error != null)
            {
                labelStatus.Text = $"错误: {e.Error.Message}";
            }
            else
            {
                labelStatus.Text = $"操作完成,结果: {e.Result}";
            }
        }
    }
}

总结

  • Thread类:适合用于需要对线程进行精细控制的场景。
  • ThreadPool:在执行短时间任务且需要复用线程的情况下是不错的选择。
  • Task Parallel Library (TPL):推荐在大多数情况下使用,尤其是需要处理任务组合和结果的场景。
  • async/await:非常适合编写异步代码,能让代码的可读性更强。
  • BackgroundWorker:专门用于Windows Forms和WPF应用程序中进行后台操作并更新UI。

你可以根据具体的使用场景,挑选最合适的线程创建方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值