前言

  在各个开发语言中,线程是避免不了的,或许通过表象看不出来,但是真的无处不在。就比如一个Web程序,平时或许只注重增删改查的开发,根本没有编写相关多线程的的代码,但是请求内部的时候,已经分配了对应线程进行处理了,以下简单说说C#中使用线程的几种方式,详细使用后续继续记录。

Thread类实现

  Thread类的实现方式,在C# .NetFramework刚出的时候就已经存在了,起初刚开始的程序员都使用这种方式,但经历后面几个.NetFramework的版本更新,实现方式变的更多了。

     public void TestThread()
{
//这里需要注意的是:在C#中线程是离不开委托的
//创建了一个线程对象,这里构造函数提供两类,一种不带参数的,一种是带参数的
Thread thread = new Thread( TestAction);
//设置线程相关属性
thread.IsBackground = true;
thread.Name = "Test";
//启动线程
thread.Start();
} /// <summary>
/// 线程执行的方法
/// </summary>
private void TestAction()
{
//这里实现线程处理的相关业务
Console.WriteLine($"子线程Thread({Thread.CurrentThread.Name})执行相关业务操作....{Thread.CurrentThread.ManagedThreadId}");
}

运行结果:

ThreadPool 线程池实现

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading; namespace MutltiThreadImplement
{
/// <summary>
/// ThreadPool 池化线程,避免频繁的申请和释放消耗资源;之前Thread每次都要申请和释放。
/// </summary>
public class ThreadPoolImplement
{
public void TestThreadPool()
{
//可以设置相关属性
ThreadPool.SetMinThreads(5,10);
ThreadPool.SetMaxThreads(6, 10); //通过线程池自动分配线程执行对应的业务功能
ThreadPool.QueueUserWorkItem(TestAction); } private void TestAction(object state)
{
//这里实现线程处理的相关业务
Console.WriteLine($"子线程Thread({Thread.CurrentThread.Name})执行相关业务操作....{Thread.CurrentThread.ManagedThreadId}");
}
}
}

  

  运行结果:

ThreadPool的使用是不是感觉比较简单,但是就是因为太简单了,在业务中有些需求得不到满足,比如试着控制线程顺序;

Delegate 实现的多线程

    public void TestDelegateThread()
{
//定义一个强类型委托, 可以自定义委托
Action action = TestAction; //开始异步操作,其实内部是开启了子线程,看线程id不一样就明白了
IAsyncResult asyncResult = action.BeginInvoke(CallBack, null); //可以根据返回对象的一些属性和方法进行判断和业务逻辑执行 具体可以查看相关文档
//asyncResult.IsCompleted; //判读是否执行完成
//asyncResult.AsyncWaitHandle.WaitOne(); //阻塞当前线程,直到收到信号量
} private void TestAction()
{
//这里实现线程处理的相关业务
Console.WriteLine($"子线程Thread({Thread.CurrentThread.Name})执行相关业务操作....{Thread.CurrentThread.ManagedThreadId}");
} /// <summary>
/// 子线程执行完成时的回调
/// </summary>
private void CallBack(IAsyncResult ar)
{
Console.WriteLine($"子线程{Thread.CurrentThread.ManagedThreadId}执行完毕");
}

运行结果:

  

注:  这种方式在.NetCore环境不支持,提示平台不支持。

BackGroundWorker 实现

    BackgroundWorker backgroundWorker = new     BackgroundWorker();

        public void TestBackGroundWorker()
{ //这里使用的是事件的方式绑定业务处理方法
backgroundWorker.DoWork += TestAction; //可以绑定一些事件 使用很简单,可以不需要绑定以下事件和设置属性就可以执行,根据需要进行绑定
//执行完成事件
backgroundWorker.RunWorkerCompleted += BackgroundWorker_RunWorkerCompleted;
backgroundWorker.ProgressChanged += BackgroundWorker_ProgressChanged;
backgroundWorker.WorkerReportsProgress = true;//只有执行这个属性之后才能进行ProgressChanged触发 //开始执行操作
backgroundWorker.RunWorkerAsync();
} /// <summary>
/// 触发事件之后的业务处理
/// </summary>
private void BackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
Console.WriteLine("可以在这里更新UI线程上的东西....");
} /// <summary>
/// 触发事件之后的业务处理
/// </summary>
private void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Console.WriteLine($"子线程{Thread.CurrentThread.ManagedThreadId}执行完成!!!");
} private void TestAction(object sender, DoWorkEventArgs e)
{
//这里实现线程处理的相关业务
Console.WriteLine($"子线程Thread({Thread.CurrentThread.Name})执行相关业务操作....{Thread.CurrentThread.ManagedThreadId}");
//在业务方法中执行ReportProgress方法会触发ProgressChanged事件
backgroundWorker.ReportProgress();
Console.WriteLine($"子线程Thread({ Thread.CurrentThread.ManagedThreadId})执行相关业务操作结束");
}

运行结果:

BackgroundWorker 这种方式比较适应于窗体应用程序。

Task 实现多线程

        /// <summary>
/// Task 实现多线程, 目前为止,Task方式是大家都比较推荐的方式
/// </summary>
public void TestTask()
{
//创建一个Task实例
Task task = new Task(TestAction);
//开始任务
task.Start();
} private void TestAction()
{
//这里实现线程处理的相关业务
Console.WriteLine($"子线程Thread({Thread.CurrentThread.Name})执行相关业务操作....{Thread.CurrentThread.ManagedThreadId}");
}

运行结果

Task实现多线程的方式是大家一致推荐的,俗称最佳实践。

Parallel实现多线程

    /// <summary>
/// Parallel 是对Task的进一步封装,但会阻塞主线程,主线程会参与业务逻辑处理
/// </summary>
public class ParallelImplement
{
public void TestParallel()
{
//分配线程执行业务逻辑,  Invoke可传多个业务处理,内部会自动分配线程处理
Parallel.Invoke(TestAction);
}
private void TestAction()
{
//这里实现线程处理的相关业务
Console.WriteLine($"子线程Thread({Thread.CurrentThread.Name})执行相关业务操作....{Thread.CurrentThread.ManagedThreadId}");
}
}

运行结果:

 

根据运行结果得出结论,主线程参与业务逻辑处理中,会阻塞线程, Parallel可根据业务进行选择使用。

总结

  以上基本上就是C#中使用多线程常用的几种方式,这里只是简单的汇总方式,没有深入分析,后续将针对模块进行分析。

 

  

C# 实现线程的常用几种方式的更多相关文章

  1. java核心知识点学习----创建线程的第三种方式Callable和Future CompletionService

    前面已经指出通过实现Runnable时,Thread类的作用就是将run()方法包装成线程执行体,那么是否可以直接把任意方法都包装成线程执行体呢?Java目前不行,但其模仿者C#中是可以的. Call ...

  2. $.ajax()方法详解 ajax之async属性 【原创】详细案例解剖——浅谈Redis缓存的常用5种方式(String,Hash,List,set,SetSorted )

    $.ajax()方法详解   jquery中的ajax方法参数总是记不住,这里记录一下. 1.url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址. 2.type: 要求为Str ...

  3. java核心知识点----创建线程的第三种方式 Callable 和 Future CompletionService

    前面已经指出通过实现Runnable时,Thread类的作用就是将run()方法包装成线程执行体,那么是否可以直接把任意方法都包装成线程执行体呢?Java目前不行,但其模仿者C#中是可以的. Call ...

  4. IOS 多线程,线程同步的三种方式

    本文主要是讲述 IOS 多线程,线程同步的三种方式,更多IOS技术知识,请登陆疯狂软件教育官网. 一般情况下我们使用线程,在多个线程共同访问同一块资源.为保护线程资源的安全和线程访问的正确性. 在IO ...

  5. .Net 中读写Oracle数据库常用两种方式

    .net中连接Oracle 的两种方式:OracleClient,OleDb转载 2015年04月24日 00:00:24 10820.Net 中读写Oracle数据库常用两种方式:OracleCli ...

  6. java多线程机制1(线程创建的两种方式)

    进程:正在运行的程序.(即程序在内存中开辟了一片空间) 线程:是进程的执行单元. 一个进程至少包含了一个多个线程. 多线程是不是可以提高效率:多线程可以合理的利用系统的资源,提高效率是相对的.因为cp ...

  7. vue动态绑定class的最常用几种方式

    vue动态绑定class的最常用几种方式:  第一种:(最简单的绑定) 1.绑定单个class html部分: <div :class="{'active':isActive}&quo ...

  8. java高并发系列 - 第11天:线程中断的几种方式

    java高并发系列第11篇文章. 本文主要探讨一下中断线程的几种方式. 通过一个变量控制线程中断 代码: package com.itsoku.chat05; import java.util.con ...

  9. JAVA - 启动线程有哪几种方式

    JAVA - 启动线程有哪几种方式 一.继承Thread类创建线程类 (1)定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务.因此把run()方法称为执行 ...

随机推荐

  1. 使用Splunk监控SAP Dump

    最近在尝试使用Splunk对SAP系统进行监控,以Dump监控为例,总结了一点相关信息,记录在这里. 本文链接:https://www.cnblogs.com/hhelibeb/p/13260385. ...

  2. lottery+web2

    lottery 题目分析 题目给了一个彩票网站,经过页面的探索,没有发现明显漏洞,进行目录扫描,发现该站存在.git文件 猜测存在源码泄露,使用githack利用: 获得网页源码,进行源码分析 源码审 ...

  3. 数据可视化实例(五): 气泡图(matplotlib,pandas)

    https://datawhalechina.github.io/pms50/#/chapter2/chapter2 关联 (Correlation) 关联图表用于可视化2个或更多变量之间的关系. 也 ...

  4. 简易防止U盘中毒

    1.将U盘插入电脑,打开u盘 2.在U盘里面新建一个文本文档,将文本文档重命名autorun.inf保存完成. 3.为了防止误删次文件可以将属性设为影藏,就完成了.

  5. ant-design-vue中实现modal模态框的复用(添加,编辑展示同一个模态框)

    用两个button(添加,编辑)按钮展示同一个模态框,并不是什么大问题,问题在于解决这两个模态框得有自己的确定和取消方法 父页面完全接管子页面(利于子页面复用) 父页面代码: <template ...

  6. Windows 磁盘分区后如何再合并&如何用Windows自带工具扩大某个分区

    Windows 磁盘分区后如何再合并&用Windows自带工具扩大某个分区 注:此方法有一定的成功率,更加完善可行的方法请看http://www.diskgenius.cn/help/part ...

  7. P1290 欧几里德的游戏(洛谷)

    欧几里德的两个后代 Stan 和 Ollie 正在玩一种数字游戏,这个游戏是他们的祖先欧几里德发明的.给定两个正整数 M 和 N,从 Stan 开始,从其中较大的一个数,减去较小的数的正整数倍,当然, ...

  8. Spring框架零基础学习(一):IOC|DI、AOP

    文章目录 一.IDEA创建Spring项目 二.Spring: IOC和DI 三.Spring: AOP 参考链接: HOW2J.CN:Spring idea创建一个spring项目 一.IDEA创建 ...

  9. 02 安装net-tools工具

    01 登录虚拟机,没错,还是那个熟悉的黑窗口 02 输入用户名密码(我还是习惯使用root用户,因为,它可以为所欲为) 小知识:注意红色框内的符号: 一般用户为限制用户,符号为:$ 超级用户,为无限制 ...

  10. Java实现一个简单的文件上传案例

    Java实现一个简单的文件上传案例 实现流程: 1.客户端从硬盘读取文件数据到程序中 2.客户端输出流,写出文件到服务端 3.服务端输出流,读取文件数据到服务端中 4.输出流,写出文件数据到服务器硬盘 ...