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,一经查实,立即删除!

相关文章

linux apache24 使用,科学网—linux_centos第24_2次课Apache的安装 - 郭会强的博文

第24次课Apache的安装下载apache的网址[rootghq~]# cd /usr/local/src[rootghqsrc]# lsmysql-5.1.40-linux-i686-icc-glibc23.tar.gz从网上下载&#xff0c;使用命令wget[rootghq src]# wgethttp://apache.fayea.com//httpd/httpd-2.2.31.tar.bz2--2015-08-2007:24:43-- http:/…

《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…

C语言 第五章 选择结构 答案,c语言第五章 选择结构程序设计(习题册答案).doc

第五章 选择结构程序设计基础练习(A)一、填空题1、关系表达式的运算结果是 逻辑 值。C语言没有逻辑型数据&#xff0c;以 1 代表“真”&#xff0c;以 0代表“假”。2、逻辑运算符&#xff01;是 单目 运算符&#xff0c;其结合性是由 右结合性 。3、C语言提供的三种逻辑运算符…

linux命令之ifconfig详细解释

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

c语言 如何连接两个程序,C语言连接两个链表程序

创建两个链表&#xff0c;并这两链表连接起来成为一个链表的示例程序&#xff0c;将以下代码保存到一个源文件中&#xff1a;combine_linked_list.c&#xff0c; 如下所示 –#include #include struct node { int data; struct node *next; }; struct node *even NULL; struct…

微信小程序UI组件、开发框架、实用库...

UI组件 weui-wxss ★852 - 同微信原生视觉体验一致的基础样式库Wa-UI ★122 - 针对微信小程序整合的一套UI库wx-charts ★105 - 微信小程序图表工具wemark ★85 - 微信小程序Markdown渲染库WeZRender ★36 - 微信小程序Canvas增强组件wetoast ★21 - 仿照微信小程序提供的showT…

c语言编程一个 图书管理,我也要用c语言编程一个图书管理系统,

#includeusing namespace std;const int N 25;//定义20本图书struct Book {char name[25];char author[15];char price[7];char publisher[20];char isbn[20];};int ii 19;Book book[N] { { "红与黑","司汤达","26.00","长江文艺出版社&…

十二个球称三次C语言编程,十二个球,有一个不知轻重,现有一个天平,称三次,找出此球!...

平均分成A、B、C三组,每组4个&#xff1b;第一秤&#xff1a;A、B两组先分别放天平左右&#xff1a;情况一&#xff1a;平衡.则问题出在C组,A、B组共8个为标准球. 第二秤用3个标准球和C组的3个球对比, 如果第二秤平衡,剩下的一个就是问题球,第三秤用标准球和问题球对比,得出问题…

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

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

解决鼠标滚动的时候多次执行函数

有这种场景&#xff0c;鼠标滚动到页面的底部的时候&#xff0c;显示剩余的数据&#xff1b; 这种情况有时候会出现的错误是鼠标滚动的时候会多次触发&#xff0c;同样的多次执行ajax&#xff0c;调取数据&#xff1b; 解决的方法是:设置一个全局变量flag&#xff0c;当鼠标滚动…

上海工程技术大学c语言,上海工程技术大学 C语言实习报告.doc

实 习 报 告《高级语言程序设计》2012&#xff5e;2013学年第 一 学期学院(部) 管理学院指导教师 李旭芳班级代号 0315121姓名/学号 张何兵/031512130同组人 无实验一一&#xff1a;实验项目名称&#xff1a;在函数中进行10个学生成绩从高到低排名 sort(int a[10])二&#xff1…

【二色汉诺塔 】

/* 二色汉诺塔 */#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语言程序设计10-第6章 利用数组处理批量数据 6.1 怎样定义和引用一维数组.ppt...

c语言程序设计10-第6章 利用数组处理批量数据 6.1 怎样定义和引用一维数组* 临沂大学汽车学院&#xff1a;韩晓翠 第6章 利用数组处理批量数据 6.1 怎样定义和引用一维数组 授课要点 数组的概念 一维数组的定义和引用 一维数组的初始化和赋值 数组元素的遍历 问题&#xff1a;从…

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;// 初始化主线…