线程处理用于使程序能够执行并发处理,同时执行多个操作。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#]线程处理的更多相关文章

  1. [ 高并发]Java高并发编程系列第二篇--线程同步

    高并发,听起来高大上的一个词汇,在身处于互联网潮的社会大趋势下,高并发赋予了更多的传奇色彩.首先,我们可以看到很多招聘中,会提到有高并发项目者优先.高并发,意味着,你的前雇主,有很大的业务层面的需求, ...

  2. [高并发]Java高并发编程系列开山篇--线程实现

    Java是最早开始有并发的语言之一,再过去传统多任务的模式下,人们发现很难解决一些更为复杂的问题,这个时候我们就有了并发. 引用 多线程比多任务更加有挑战.多线程是在同一个程序内部并行执行,因此会对相 ...

  3. 多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类)

    前言:刚学习了一段机器学习,最近需要重构一个java项目,又赶过来看java.大多是线程代码,没办法,那时候总觉得多线程是个很难的部分很少用到,所以一直没下决定去啃,那些年留下的坑,总是得自己跳进去填 ...

  4. Java 线程

    线程:线程是进程的组成部分,一个进程可以拥有多个线程,而一个线程必须拥有一个父进程.线程可以拥有自己的堆栈,自己的程序计数器和自己的局部变量,但不能拥有系统资源.它与父进程的其他线程共享该进程的所有资 ...

  5. C++实现线程安全的单例模式

    在某些应用环境下面,一个类只允许有一个实例,这就是著名的单例模式.单例模式分为懒汉模式,跟饿汉模式两种. 首先给出饿汉模式的实现 template <class T> class sing ...

  6. 记一次tomcat线程创建异常调优:unable to create new native thread

    测试在进行一次性能测试的时候发现并发300个请求时出现了下面的异常: HTTP Status 500 - Handler processing failed; nested exception is ...

  7. Android线程管理之ThreadLocal理解及应用场景

    前言: 最近在学习总结Android的动画效果,当学到Android属性动画的时候大致看了下源代码,里面的AnimationHandler存取使用了ThreadLocal,激起了我很大的好奇心以及兴趣 ...

  8. C#多线程之线程池篇3

    在上一篇C#多线程之线程池篇2中,我们主要学习了线程池和并行度以及如何实现取消选项的相关知识.在这一篇中,我们主要学习如何使用等待句柄和超时.使用计时器和使用BackgroundWorker组件的相关 ...

  9. C#多线程之线程池篇2

    在上一篇C#多线程之线程池篇1中,我们主要学习了如何在线程池中调用委托以及如何在线程池中执行异步操作,在这篇中,我们将学习线程池和并行度.实现取消选项的相关知识. 三.线程池和并行度 在这一小节中,我 ...

  10. C#多线程之线程池篇1

    在C#多线程之线程池篇中,我们将学习多线程访问共享资源的一些通用的技术,我们将学习到以下知识点: 在线程池中调用委托 在线程池中执行异步操作 线程池和并行度 实现取消选项 使用等待句柄和超时 使用计时 ...

随机推荐

  1. char数组与char指针

    1.以字符串形式出现的,编译器会在结尾自动添加\0,思考,为什么? 存在的C语言方法,如strlen(s),计算字符串的长度,其中s指针.strlen要计算字符串长度,必须知道哪里是结尾,因此使用\0 ...

  2. 2015南阳CCPC H - Sudoku 暴力

    H - Sudoku Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 无 Description Yi Sima was one of the best cou ...

  3. C# WinForm 上传图片,文件到服务器的方法Uploader.ashx

    网上有很多方案,起初用时,因为对asp.net不太了解,觉得FTP实现不错,可是后来发现,如果机器在域控下,就会有问题. 一年过去了,asp.net也熟悉了,知道ajax没事应该用ashx,验证码也用 ...

  4. HDU 1080 DP

    匹配两个人相似度. A,G,C.T.每两个都会有一个相应的值,给出两串基因.长度能够不一样,能够在基因中间加_使两串长度一样.然后有一个相应值.求最大相应值. 先做出相应的表 DP方程: x=dp[i ...

  5. 最简单的视频编码器:编译(libx264,libx265,libvpx)

    ===================================================== 最简单的视频编码器系列文章列表: 最简单的视频编码器:编译 最简单的视频编码器:基于libx ...

  6. ios开发——实用技术篇&XML协议详解

    XML的数据协议组成 名词 说明 md5 message-digest algorithm 5 http hypertext transfer protocol xml extensible mark ...

  7. enum 在c中的使用

    假设一个变量你须要几种可能存在的值,那么就能够被定义成为枚举类型.之所以叫枚举就是说将变量或者叫对象可能存在的情况也能够说是可能的值一一例举出来.  举个样例来说明一吧,为了让大家更明确一点,比方一个 ...

  8. dup和dup2函数

    下面两个函数都可用来复制一个现存的文件描述符: #include<unistd.h> int dup(int filedes); int dup2(int filedes,int file ...

  9. 进程间通信之FIFO

    FIFO有时被称为命名管道.管道只能由相关进程使用,这些相关进程的共同祖先进程创建了管道.但是,通过FIFO,不相关的进程也能交换数据. FIFO是一种文件类型(参考http://www.cnblog ...

  10. 进程间通信之popen和pclose函数

    常见的操作是创建一个管道连接到另一个进程,然后读其输出或向其输入端发送数据,为此,标准I/O库提供了两个函数popen和pclose.这两个函数实现的操作是:创建一个管道,调用fork产生一个子进程, ...