C#多线程编程

C#多线程编程

一、使用线程的理由

1、可以使用线程将代码同其他代码隔离,提高应用程序的可靠性。

2、可以使用线程来简化编码。

3、可以使用线程来实现并发执行。

二、基本知识

1、进程与线程:进程作为操作系统执行程序的基本单位,拥有应用程序的资源,进程包含线程,进程的资源被线程共享,线程不拥有资源。

2、前台线程和后台线程:通过Thread类新建线程默认为前台线程。当所有前台线程关闭时,所有的后台线程也会被直接终止,不会抛出异常。

3、挂起(Suspend)和唤醒(Resume):由于线程的执行顺序和程序的执行情况不可预知,所以使用挂起和唤醒容易发生死锁的情况,在实际应用中应该尽量少用。

4、阻塞线程:Join,阻塞调用线程,直到该线程终止。

5、终止线程:Abort:抛出 ThreadAbortException 异常让线程终止,终止后的线程不可唤醒。Interrupt:抛出 ThreadInterruptException 异常让线程终止,通过捕获异常可以继续执行。

6、线程优先级:AboveNormal BelowNormal Highest Lowest Normal,默认为Normal。

三、线程的使用

线程函数通过委托传递,可以不带参数,也可以带参数(只能有一个参数),可以用一个类或结构体封装参数。

复制代码
namespace Test
{class Program{static void Main(string[] args){Thread t1 = new Thread(new ThreadStart(TestMethod));Thread t2 = new Thread(new ParameterizedThreadStart(TestMethod));t1.IsBackground = true;t2.IsBackground = true;t1.Start();t2.Start("hello");Console.ReadKey();}public static void TestMethod(){Console.WriteLine("不带参数的线程函数");}public static void TestMethod(object data){string datastr = data as string;Console.WriteLine("带参数的线程函数,参数为:{0}", datastr);}} 
}
复制代码

四、线程池

由于线程的创建和销毁需要耗费一定的开销,过多的使用线程会造成内存资源的浪费,出于对性能的考虑,于是引入了线程池的概念。线程池维护一个请求队列,线程池的代码从队列提取任务,然后委派给线程池的一个线程执行,线程执行完不会被立即销毁,这样既可以在后台执行任务,又可以减少线程创建和销毁所带来的开销。

线程池线程默认为后台线程(IsBackground)。

复制代码
namespace Test
{class Program{static void Main(string[] args){//将工作项加入到线程池队列中,这里可以传递一个线程参数ThreadPool.QueueUserWorkItem(TestMethod, "Hello");Console.ReadKey();}public static void TestMethod(object data){string datastr = data as string;Console.WriteLine(datastr);}}
}
复制代码

五、Task类

使用ThreadPool的QueueUserWorkItem()方法发起一次异步的线程执行很简单,但是该方法最大的问题是没有一个内建的机制让你知道操作什么时候完成,有没有一个内建的机制在操作完成后获得一个返回值。为此,可以使用System.Threading.Tasks中的Task类。

构造一个Task<TResult>对象,并为泛型TResult参数传递一个操作的返回类型。

复制代码
namespace Test
{class Program{static void Main(string[] args){Task<Int32> t = new Task<Int32>(n => Sum((Int32)n), 1000);t.Start();t.Wait();Console.WriteLine(t.Result);Console.ReadKey();}private static Int32 Sum(Int32 n){Int32 sum = 0;for (; n > 0; --n)checked{ sum += n;} //结果太大,抛出异常return sum;}}
}
复制代码

一个任务完成时,自动启动一个新任务。
一个任务完成后,它可以启动另一个任务,下面重写了前面的代码,不阻塞任何线程。

复制代码
namespace Test
{class Program{static void Main(string[] args){Task<Int32> t = new Task<Int32>(n => Sum((Int32)n), 1000);t.Start();//t.Wait();Task cwt = t.ContinueWith(task => Console.WriteLine("The result is {0}",t.Result));Console.ReadKey();}private static Int32 Sum(Int32 n){Int32 sum = 0;for (; n > 0; --n)checked{ sum += n;} //结果溢出,抛出异常return sum;}}
}
复制代码

六、委托异步执行

委托的异步调用:BeginInvoke() 和 EndInvoke()

复制代码
namespace Test
{public delegate string MyDelegate(object data);class Program{static void Main(string[] args){MyDelegate mydelegate = new MyDelegate(TestMethod);IAsyncResult result = mydelegate.BeginInvoke("Thread Param", TestCallback, "Callback Param");//异步执行完成string resultstr = mydelegate.EndInvoke(result);}//线程函数public static string TestMethod(object data){string datastr = data as string;return datastr;}//异步回调函数public static void TestCallback(IAsyncResult data){Console.WriteLine(data.AsyncState);}}
}
复制代码

七、线程同步

  1)原子操作(Interlocked):所有方法都是执行一次原子读取或一次写入操作。

  2)lock()语句:避免锁定public类型,否则实例将超出代码控制的范围,定义private对象来锁定。

  3)Monitor实现线程同步

    通过Monitor.Enter() 和 Monitor.Exit()实现排它锁的获取和释放,获取之后独占资源,不允许其他线程访问。

    还有一个TryEnter方法,请求不到资源时不会阻塞等待,可以设置超时时间,获取不到直接返回false。

  4)ReaderWriterLock

    当对资源操作读多写少的时候,为了提高资源的利用率,让读操作锁为共享锁,多个线程可以并发读取资源,而写操作为独占锁,只允许一个线程操作。

  5)事件(Event)类实现同步

    事件类有两种状态,终止状态和非终止状态,终止状态时调用WaitOne可以请求成功,通过Set将时间状态设置为终止状态。

    1)AutoResetEvent(自动重置事件)

    2)ManualResetEvent(手动重置事件)

  6)信号量(Semaphore)

      信号量是由内核对象维护的int变量,为0时,线程阻塞,大于0时解除阻塞,当一个信号量上的等待线程解除阻塞后,信号量计数+1。

      线程通过WaitOne将信号量减1,通过Release将信号量加1,使用很简单。

  7)互斥体(Mutex)

      独占资源,用法与Semaphore相似。

   8)跨进程间的同步

      通过设置同步对象的名称就可以实现系统级的同步,不同应用程序通过同步对象的名称识别不同同步对象。

 

 

作者:阿凡卢
出处:http://www.cnblogs.com/luxiaoxun/

转载于:https://www.cnblogs.com/mjq5150/p/6273274.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/429700.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《DSP using MATLAB 》示例Example6.3

代码&#xff1a; C0 0; B1 [2 4; 3 1]; A1 [1 1 0.9; 1 0.4 -0.4]; B2 [0.5 0.7; 1.5 2.5; 0.8 1]; A2 [1 -1 0.8; 1 0.5 0.5; 1 0 -0.5]; [b1, a1] par2dir(C0, B1, A1)[b2, a2] par2dir(C0, B2, A2)b conv(b1, b2) % Overall direct form numerator a conv(a1…

简单说明c语言程序步骤,C语言的入门简介和三个简单的C语言程序详细说明

学习一种编程语言&#xff0c;最重要的是建立一个练习环境&#xff0c;边学边练才能学好。Keil软件是目前最流行开发80C51系列单片机的软件&#xff0c;Keil提供了包括C编译器、宏汇编、连接器、库管理和一个功能强大的仿真调试器等在内的完整开发方案&#xff0c;通过一个集成…

java入门,学习笔记

编译 通过javac编译java程序&#xff0c;会编译出一个后缀为class的文件&#xff0c;我们再通过java虚拟机&#xff08;jvm&#xff09;执行编译后的java程序。 在java中始终有一个main函数&#xff0c;它作为程序的入口&#xff0c;程序从这个入口开始执行一直到结束。 public…

linux命令之ifconfig详细解释

依赖于ifconfig命令中使用一些选项属性&#xff0c;ifconfig工具不仅可以被用来简单地获取网络接口配置信息&#xff0c;还可以修改这些配置。 1&#xff0e;命令格式&#xff1a; ifconfig [网络设备] [参数] 2&#xff0e;命令功能&#xff1a; ifconfig 命令用来查看和配置网…

loadrunner controller:实时查看VUser的运行情况

1) 如下图&#xff0c;在Run标签页&#xff0c;点击“Vusers...”打开Vuser窗口&#xff1b; 2) 如下图选中一个Vuser点击按钮可以打开Run-Time Viewer窗口&#xff0c;RTV窗口页面显示的就是该Vuser当前的操作&#xff1b; 3) 如下图所示&#xff0c;…

【二色汉诺塔 】

/* 二色汉诺塔 */#include <stdio.h>void hanoi(int disks, char sources, char temp, char target) {if(disks 1){printf("move disk from %c to %c \n", sources, target);printf("move disk from %c to %c \n", sources, target);}else{hanoi(d…

c语言凸包算法,基于C语言的凸包算法实现

基于C语言的凸包算法实现非计算机专业&#xff0c;代码有些的不好的地方&#xff0c;大佬轻喷^ _ ^根据要求&#xff0c;需要使用C语言实现凸包算法——Graham扫描法&#xff0c;本文将从算法理解、实现思路、遇到的问题及其解决方案三个方面来阐述实现过程。算法理解凸包算法G…

VS Code 使用小技巧

所有插件查找地址&#xff08;https://marketplace.visualstudio.com/&#xff09; 编码快捷方式&#xff08;http://docs.emmet.io/cheat-sheet/&#xff09; 安装插件出现 错误unable to verify the first certificate &#xff08;无法确认第一证书&#xff09;   解决方…

android 怎么自定义任务栈,Android中的Activity详解--启动模式与任务栈

目录Activity生命周期任务栈启动模式Intent FlagtaskAffinity属性1.Activityactivity的简单介绍就不写了&#xff0c;作为最常用的四大组件之一&#xff0c;肯定都很熟悉其基本用法了。2.生命周期首先&#xff0c;是都很熟悉的一张图&#xff0c;即官方介绍的Activity生命周期图…

SQL Server--疑难杂症之坑爹的Windows故障转移群集

-- 估计是春节前最后一次写博客&#xff0c;也估计是本年值班最后一次踩雷&#xff0c;感叹下成也SQL SERVER&#xff0c;败也SQL SERVER。 -- 场景描述&#xff1a; 操作系统版本 &#xff1a;Windows Server 2012 数据中心版本 数据库版本 &#xff1a;SQL SERVER 2012 企业版…

android handle 阻塞,Android全面解析之Handler机制:常见问题汇总

主线程为什么不用初始化Looper&#xff1f;答&#xff1a;因为应用在启动的过程中就已经初始化主线程Looper了。每个java应用程序都是有一个main方法入口&#xff0c;Android是基于Java的程序也不例外。Android程序的入口在ActivityThread的main方法中&#xff1a;// 初始化主线…

UML中的6大关系(关联、依赖、聚合、组合、泛化、实现)

UML定义的关系主要有六种&#xff1a;依赖、类属、关联、实现、聚合和组合。这些类间关系的理解和使用是掌握和应用UML的关键&#xff0c;而也就是这几种关系&#xff0c;往往会让初学者迷惑。这里给出这六种主要UML关系的说明和类图描述&#xff0c;一看之下&#xff0c;清晰明…

性能调优-硬盘方面,操作系统方面,文件系统方面

硬盘对数据库性能的影响 传统机械硬盘 当前大多数数据库使用的都是传统的机械硬盘。机械硬盘的技术目前已非常成熟&#xff0c;在服务器领域一般使用SAS或SATA接口的硬盘。服务器机械硬盘开始向小型化转型&#xff0c;目前已经有大量2.5寸的SAS机械硬盘。 机械硬盘有两个重要的…

chrome Android 80,Chrome OS 80将为Chromebook带来侧载Android应用的支持

如需体验这项功能&#xff0c;需在启动 Crostini 容器时加上一行特殊的命令 —— 从 Chromebook 命令行启动时&#xff0c;请加上 –enable-features ArcAdbSideloading 。最终&#xff0c;我们希望这回成为一项明示的标记(flags)功能。如变更日志所述&#xff0c;用户可通过托…

android 日历仿IOS,基于Android week view仿小米和iphone日历效果

前言最近由于项目需求&#xff0c;要做一个仿小米日历的功能&#xff0c;下面显示一天的日程&#xff0c;header以周为单位进行滑动&#xff0c;github上找了很久也没有找到合适的&#xff0c;但找到一相近的开源项目Android-week-view&#xff0c;它不是我们项目所需要的效果&…

1、管理员登录中间件和注销

1、根据session去判断用户是否登录&#xff0c;登录后才可以进index首页&#xff0c;否则返回login页面&#xff0c;借助中间件 (1)修改路由 Route::group([middleware > [web,admin.login],prefix>admin,namespace>Admin], function () { //注册一个中间件admin.logi…

HTML阅读打开点击不了,如何让网页文章中的代码可以点击运行

在网页中运行代码HTML5学堂&#xff1a;很多代码网站当中&#xff0c;都会提供运行代码段功能&#xff0c;便于查看代码效果&#xff0c;那么这个是如何实现的呢&#xff1f;一起来看一下——如何在网页中运行代码。HTML5学堂-刘国利said&#xff1a;应该是在2013年的时候&…

html留言回复评论页面模板,HTML5实现留言和回复的页面样式

这篇文章主要介绍了用HTML5如何实现留言和回复样式,需要的朋友可以参考下具体就不做详细讲解了&#xff0c;直接上代码&#xff1a;web开发-webkfa.com*{margin:0;padding:0;-webkit-touch-callout: none; /* prevent callout to copy image, etc when tap to hold */-webkit-t…

html5列表菜单特效,HTML5 SVG汉堡包菜单按钮分段动画特效

这是一款效果非常炫酷的HTML5 SVG汉堡包菜单按钮分段动画特效。该菜单按钮特效在用户点击汉堡包按钮时&#xff0c;按钮会分割为多段&#xff0c;并旋转变形为关闭按钮的状态。当再次点击该按钮时&#xff0c;它会逆向变形为汉堡包图标。该特效是基于Segment.js插件(一款可以只…

计算机选修课学什么,计算机专业都学什么 主要课程有什么

计算机专业的主要学习内容有什么呢&#xff0c;都开设哪些课程呢&#xff0c;下面小编为大家提供计算机专业主要学习内容&#xff0c;仅供大家参考。计算机专业主要学习内容一、数学类主要课程&#xff1a;高等数学、线性代数、离散数学、概率论、数理统计二、语言类主要课程&a…