前言

  在各个开发语言中,线程是避免不了的,或许通过表象看不出来,但是真的无处不在。就比如一个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. day76 作业

    目录 需求: 作业1: 作业2: 需求: 1. 在作业1.html代码的基础上,引入vue.js文件,并实例化vm对象,绑定#goods元素 2. 在作业1.html代码的基础上,默认中间弹出窗口隐藏 ...

  2. Python并发编程——多线程与协程

    Pythpn并发编程--多线程与协程 目录 Pythpn并发编程--多线程与协程 1. 进程与线程 1.1 概念上 1.2 多进程与多线程--同时执行多个任务 2. 并发和并行 3. Python多线 ...

  3. 关于Pop!_OS 19.04有线网络始终正在连接

    一开始使用Pop!_OS时就遇到这个问题,开机进入系统后明明网络没问题,WiFi正常可用, 但是插入网线后有线网络始终显示正在连接,然后可能过一会儿还会弹出来网络激活失败. 但是有可能在使用很久之后再 ...

  4. 机器学习实战基础(八):sklearn中的数据预处理和特征工程(一)简介

    1 简介 数据挖掘的五大流程: 1. 获取数据 2. 数据预处理 数据预处理是从数据中检测,纠正或删除损坏,不准确或不适用于模型的记录的过程 可能面对的问题有:数据类型不同,比如有的是文字,有的是数字 ...

  5. project facet java 1.8 is not supported解决办法

    Right click on project -> Properties -> Search for Project Facets -> Java (Version)

  6. SqlServer同义词

    最近在项目中遇到跨库操作具有相同表结构的数据表的问题.(A库中的数据表a和B库中的数据表b,两者表结构相同) 跨库操作中我们一般是为了实现不同数据库中表字段信息,字段状态等实时同步,可能很多人会想到使 ...

  7. rabbitmq+sleuth+zinkip 分布式链路追踪

    我们都知道,微服务之间通过feign传递,在复杂的微服务架构系统中,几乎每一个前端请求都会形成一个复杂的分布式服务调用链路,在每条链路中任何一个依赖服务出现延迟超时或者错误都有可能引起整个请求最后的失 ...

  8. Ethical Hacking - Web Penetration Testing(10)

    SQL INJECTION SQLMAP Tool designed to exploit SQL injections. Works with many DB types, MySQL, MSSQL ...

  9. Porter 进入 CNCF 云原生全景图,新版本即将发布!

    近日,KubeSphere 社区子项目面向物理机环境的负载均衡器 Porter 正式进入 CNCF Landscape.CNCF Landscape 在云原生实践过程中的每个环节帮助用户了解有哪些具体 ...

  10. ES6语法——Promise对象

    一.概念 Promise是异步编程的一种解决方案(解决回调地狱的问题),是一个能够获取异步操作信息的对象.Promise的内部保存着某个未来才会结束的事件(通常是一个异步操作) 二.特点 1.Prom ...