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), );
t.Start();
t.Wait();
Console.WriteLine(t.Result);
Console.ReadKey();
} private static Int32 Sum(Int32 n)
{
Int32 sum = ;
for (; n > ; --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), );
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 = ;
for (; n > ; --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)跨进程间的同步
通过设置同步对象的名称就可以实现系统级的同步,不同应用程序通过同步对象的名称识别不同同步对象。
C#多线程编程的更多相关文章
- Web Worker javascript多线程编程(一)
什么是Web Worker? web worker 是运行在后台的 JavaScript,不占用浏览器自身线程,独立于其他脚本,可以提高应用的总体性能,并且提升用户体验. 一般来说Javascript ...
- Web Worker javascript多线程编程(二)
Web Worker javascript多线程编程(一)中提到有两种Web Worker:专用线程dedicated web worker,以及共享线程shared web worker.不过主要讲 ...
- windows多线程编程实现 简单(1)
内容:实现win32下的最基本多线程编程 使用函数: #CreateThread# 创建线程 HANDLE WINAPI CreateThread( LPSECURITY_ATTRIBUTES lpT ...
- Rust语言的多线程编程
我写这篇短文的时候,正值Rust1.0发布不久,严格来说这是一门兼具C语言的执行效率和Java的开发效率的强大语言,它的所有权机制竟然让你无法写出线程不安全的代码,它是一门可以用来写操作系统的系统级语 ...
- windows多线程编程星球(一)
以前在学校的时候,多线程这一部分是属于那种充满好奇但是又感觉很难掌握的部分.原因嘛我觉得是这玩意儿和编程语言无关,主要和操作系统的有关,所以这部分内容主要出现在讲原理的操作系统书的某一章,看完原理是懂 ...
- Java多线程编程核心技术---学习分享
继承Thread类实现多线程 public class MyThread extends Thread { @Override public void run() { super.run(); Sys ...
- python多线程编程
Python多线程编程中常用方法: 1.join()方法:如果一个线程或者在函数执行的过程中调用另一个线程,并且希望待其完成操作后才能执行,那么在调用线程的时就可以使用被调线程的join方法join( ...
- 浅述WinForm多线程编程与Control.Invoke的应用
VS2008.C#3.0在WinForm开发中,我们通常不希望当窗体上点了某个按钮执行某个业务的时候,窗体就被卡死了,直到该业务执行完毕后才缓过来.一个最直接的方法便是使用多线程.多线程编程的方式在W ...
- Java—多线程编程
一个多线程程序包含两个或多个能并发运行的部分.程序的每一部分都称作一个线程,并且每个线程定义了一个独立的执行路径. 进程:一个进程包括由操作系统分配的内存空间,包含一个或多个线程.一个线程不能独立的存 ...
- [转]Linux 的多线程编程的高效开发经验
Linux 平台上的多线程程序开发相对应其他平台(比如 Windows)的多线程 API 有一些细微和隐晦的差别.不注意这些 Linux 上的一些开发陷阱,常常会导致程序问题不穷,死锁不断.本文中我们 ...
随机推荐
- 我如何介绍 Microservice
这篇文章转自我的 Github blog 一天我司招财猫姐(HR 大人)问我,你给我解释一下 Microservice 是什么吧.故成此文.一切都是从一个创业公司开始的. 故事 最近的创业潮非常火爆, ...
- ASP.NET MVC 从零开始 - 自动化部署(其二)
这篇文章是从我的 github 博客 http://lxconan.github.io 导入的. 这是这个系列的第五篇了,前四篇请参见: ASP.NET MVC 从零开始 – Create and R ...
- Module-Zero之租户管理
返回<Module Zero学习目录> 开启多租户 租户实体 租户管理者 默认租户 开启多租户 ABP和Module-Zero可以运行多租户或单租户模式.多租户默认是禁用的.我们可以在mo ...
- 《Entity Framework 6 Recipes》中文翻译系列 (35) ------ 第六章 继承与建模高级应用之TPH继承映射中使用复合条件
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-11 TPH继承映射中使用复合条件 问题 你想使用TPH为一张表建模,建模中使 ...
- Google Chrome调试js入门
平常在开发过程中,经常会接触到前端页面.那么对于js的调试那可是家常便饭,不必多说.最近一直在用火狐的Firebug,但是不知道怎么的不好使了.网上找找说法,都说重新安装狐火浏览器就可以了,但是我安装 ...
- 使用sklearn进行集成学习——实践
系列 <使用sklearn进行集成学习——理论> <使用sklearn进行集成学习——实践> 目录 1 Random Forest和Gradient Tree Boosting ...
- js实用篇之String对象
概述 String对象是JavaScript原生提供的三个包装对象之一,用来生成字符串的包装对象. var s1 = 'abc'; var s2 = new String('abc'); typeof ...
- ASP.net 常用服务器控件
新人初学,有错请指,大神轻喷. .net中有HTML控件和标准服务器控件. 老师教学用的是vs2010是这样分的,不知道15里是不是这样. 如果使用HTML控件我们就会发现页面中加载了原本HTML代码 ...
- MySQL GROUP BY用法
背景介绍 最近在设计数据库的时候因为开始考虑不周,所以产生了大量的重复数据.现在需要把这些重复的数据删除掉,使用到的语句就是Group By来完成.为了进一步了解这条语句的作用,我打算先从简单入手. ...
- 如何在多线程leader-follower模式下正确的使用boost::asio。
#include <assert.h> #include <signal.h> #include <unistd.h> #include <iostream& ...