[C#]线程处理
线程处理用于使程序能够执行并发处理,同时执行多个操作。C#中有三种线程的使用方法,BackgroundWorker组件、线程池、自己创建使用线程,接下来分别介绍如何使用。
1.使用BackgroundWorker组件(创建多线程处理程序最可靠方法)
此类管理一个专用于处理指定方法的单独线程。
添加 DoWork 事件的事件处理程序,为后台操作做好准备,在此事件处理程序中调用耗时的操作。
调用 RunWorkerAsync 函数,开始后台操作。
处理 ProgressChanged 事件,收到进度更新的通知。
处理RunWorkerCompleted 事件,在操作完成时收到通知。
处理 ProgressChanged 和 RunWorkerCompleted 事件的方法可以访问应用程序的用户界面,原因是这两个事件是在调用了 RunWorkerAsync 方法的线程上引发的。 但是,DoWork 事件处理程序无法使用任何用户界面对象,因为它在后台线程上运行。
2.线程池,是可以用来在后台执行多个任务的线程集合,将任务添加到队列,然后在创建线程后自动启动这些任务。线程池通常用于服务器应用程序。 每个传入请求都将分配给线程池中的一个线程,因此可以异步处理请求,而不会占用主线程,也不会延迟后续请求的处理。一旦池中的某个线程完成任务,它将返回到等待线程队列中,等待被再次使用,这种重用使应用程序可以避免为每个任务创建新线程的开销。线程池通常具有最大线程数限制。如果所有线程都繁忙,则额外的任务将放入队列中,直到有线程可用时才能够得到处理。
ThreadPool.QueueUserWorkItem(WaitCallback callBack)//将方法排入队列以便执行。 ThreadPool.QueueUserWorkItem(WaitCallback callBack, object state)//将方法排入队列以便执行,并指定包含该方法所用数据的对象。
3.创建和使用线程
如果需要对应用程序的线程的行为进行更多的控制,则可以自己管理线程。通过声明类型为 Thread 的变量,并调用为要对新线程执行的过程或方法提供名称的构造函数,从而创建一个新线程。
System.Threading.Thread newThread = new System.Threading.Thread(AMethod);
线程其他知识点:
1.前台/后台线程
后台线程与前台线程完全一样,只是后台线程不会阻止进程终止。前台线程的运行时间不限定,而后台线程则在最后一个前台线程停止时立即停止。 可以使用 IsBackground 属性确定或更改线程的后台状态。默认情况下,主线程、通过Thread类构造函数创建的线程在前台执行,线程池线程、从非托管代码进入托管环境的线程在后台执行。
2.线程的参数和返回值
为线程提供参数:将目标方法包裹在类中,并为该类定义字段,这些字段将被用作新线程的参数。
从线程获取返回值:使用BackgroundWorker 组件来管理线程,在任务完成时引发RunWorkerCompleted 事件,然后用事件处理程序处理结果。
3.线程同步
在应用程序中使用多个线程,必须协调对资源(如文件句柄、网络连接和内存)的访问。C#中的线程同步方法有锁、监视器、同步事件和等待句柄、Mutex对象、Interlocked类、ReaderWriter锁。
锁:lock 关键字将语句块标记为临界区,方法是获取给定对象的互斥锁,执行语句,然后释放该锁。
监视器:与lock关键字类似,防止多个线程同时执行代码块,但是lock更简洁、更安全。
同步事件和等待句柄:同步事件有终止、非终止两个状态的对象,用来激活和挂起线程,让线程等待一个非终止同步事件可以将线程挂起,将事件状态变为终止可以激活线程。如果线程尝试等待已经终止的事件,则线程继续执行,不会受到延迟。同步事件有AutoResetEvent和ManualResetEvent两种,只要AutoResetEvent 激活线程,其状态自动从终止变为非终止,ManualResetEvent 允许它的终止状态激活任意个线程,并只有调用其Reset方法时才还原到非终止状态。
通过调用WaitOne、WaitAny、WaitAll等待方法使线程等待事件,当调用事件的Set方法,事件变为终止状态。
using System;
using System.Threading; class ThreadingExample
{
static AutoResetEvent autoEvent; static void DoWork()
{
Console.WriteLine(" worker thread started, now waiting on event...");
autoEvent.WaitOne();
Console.WriteLine(" worker thread reactivated, now exiting...");
} static void Main()
{
autoEvent = new AutoResetEvent(false); Console.WriteLine("main thread starting worker thread...");
Thread t = new Thread(DoWork);
t.Start(); Console.WriteLine("main thread sleeping for 1 second...");
Thread.Sleep(); Console.WriteLine("main thread signaling worker thread...");
autoEvent.Set(); Console.ReadLine();
}
}
执行结果

Mutex 对象,与监视器类似。
Interlock类,使用 Interlocked 类的方法来避免在多个线程尝试同时更新或比较同一个值时可能出现的问题。使用这个类的方法可以安全地递增、递减、交换和比较任何线程中的值。
ReadWriter锁,只在写入数据时锁定资源,在不更新数据时允许多个客户端同时读取数据。 ReaderWriterLock 类在线程修改资源时将强制其独占访问资源,但在读取资源时则允许非独占访问。ReaderWriterLock 类定义支持单个写线程和多个读线程的锁。
死锁,多线程应用程序始终存在deadlock 的危险,在编码前多考虑,避免死锁。
4.线程计时器。System.Threading.Timer 类可用于定期在单独的线程上运行任务,创建实例后计时器开始启动。
参考https://msdn.microsoft.com/zh-cn/library/ms173178.aspx
[C#]线程处理的更多相关文章
- [ 高并发]Java高并发编程系列第二篇--线程同步
高并发,听起来高大上的一个词汇,在身处于互联网潮的社会大趋势下,高并发赋予了更多的传奇色彩.首先,我们可以看到很多招聘中,会提到有高并发项目者优先.高并发,意味着,你的前雇主,有很大的业务层面的需求, ...
- [高并发]Java高并发编程系列开山篇--线程实现
Java是最早开始有并发的语言之一,再过去传统多任务的模式下,人们发现很难解决一些更为复杂的问题,这个时候我们就有了并发. 引用 多线程比多任务更加有挑战.多线程是在同一个程序内部并行执行,因此会对相 ...
- 多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类)
前言:刚学习了一段机器学习,最近需要重构一个java项目,又赶过来看java.大多是线程代码,没办法,那时候总觉得多线程是个很难的部分很少用到,所以一直没下决定去啃,那些年留下的坑,总是得自己跳进去填 ...
- Java 线程
线程:线程是进程的组成部分,一个进程可以拥有多个线程,而一个线程必须拥有一个父进程.线程可以拥有自己的堆栈,自己的程序计数器和自己的局部变量,但不能拥有系统资源.它与父进程的其他线程共享该进程的所有资 ...
- C++实现线程安全的单例模式
在某些应用环境下面,一个类只允许有一个实例,这就是著名的单例模式.单例模式分为懒汉模式,跟饿汉模式两种. 首先给出饿汉模式的实现 template <class T> class sing ...
- 记一次tomcat线程创建异常调优:unable to create new native thread
测试在进行一次性能测试的时候发现并发300个请求时出现了下面的异常: HTTP Status 500 - Handler processing failed; nested exception is ...
- Android线程管理之ThreadLocal理解及应用场景
前言: 最近在学习总结Android的动画效果,当学到Android属性动画的时候大致看了下源代码,里面的AnimationHandler存取使用了ThreadLocal,激起了我很大的好奇心以及兴趣 ...
- C#多线程之线程池篇3
在上一篇C#多线程之线程池篇2中,我们主要学习了线程池和并行度以及如何实现取消选项的相关知识.在这一篇中,我们主要学习如何使用等待句柄和超时.使用计时器和使用BackgroundWorker组件的相关 ...
- C#多线程之线程池篇2
在上一篇C#多线程之线程池篇1中,我们主要学习了如何在线程池中调用委托以及如何在线程池中执行异步操作,在这篇中,我们将学习线程池和并行度.实现取消选项的相关知识. 三.线程池和并行度 在这一小节中,我 ...
- C#多线程之线程池篇1
在C#多线程之线程池篇中,我们将学习多线程访问共享资源的一些通用的技术,我们将学习到以下知识点: 在线程池中调用委托 在线程池中执行异步操作 线程池和并行度 实现取消选项 使用等待句柄和超时 使用计时 ...
随机推荐
- node搜索codeforces 3A - Shortest path of the king
发一下牢骚和主题无关: 搜索,最短路都可以 每日一道理 人生是洁白的画纸,我们每个人就是手握各色笔的画师:人生也是一条看不到尽头的长路,我们每个人则是人生道路的远足者:人生还像是一块神奇的土地 ...
- c# ado 连接数据库 六步曲
建立连接分为六步:1.定义连接字符串,oracle 的连接字符串为: private static string connString = "Data Source=192.168.1.13 ...
- 使用GLSL实现更多数量的局部光照 【转】
原文 http://www.cnblogs.com/CGDeveloper/archive/2008/07/02/1233816.html 众所周知,OpenGL固定管线只提供了最多8盏灯光.如何使得 ...
- ListView往TreView里面拖拽
ListView往TreView里面拖拽 unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Class ...
- Android开发学习之 定制界面风格
统一的用户界面是可以使得应用程序更友好.要做到用户界面的统一,我们就必须用到风格(style)和主题(theme).OPhone系统提供了很多系统默认的风格和主题,但是很多情况下,这些不能满足我们的需 ...
- [MODX] 2. Chunks $
Chunk in Modx can cut your template into samll pieces to make code reuseable. [[$chunk_name]] For ex ...
- 和Timesten有个约会--Timesten技术专栏系列(一)
作者: 三十而立 时间:2009年10月03日 12:08:42 本文出自 “inthirties(三十而立)”博客,转载请务必注明作者和保留出处http://blog.csdn.net/inthir ...
- Python学习 之 异常
1.python中处理异常的方式 #coding:utf8 filename=raw_input("请输入你要操作的文件") try: f=open(filename) print ...
- sqlserver 字符串相关函数
http://www.cnblogs.com/jiajiayuan/archive/2011/06/16/2082488.html 以下所有例子均Studnet表为例: 计算字符串长度len()用来 ...
- SQL SERVER 中identity用法
在数据库中, 常用的一个流水编号通常会使用 identity 栏位来进行设置, 这种编号的好处是一定不会重覆, 而且一定是唯一的, 这对table中的唯一值特性很重要, 通常用来做客户编号, 订单编号 ...