CWinForm多线程开发剖析
C语言中的多线程编程

C语言中的多线程编程多线程编程是指在一个程序中同时运行多个线程,这些线程可以并行执行不同的任务,以提高程序的效率和并发性。
在C语言中,可以使用标准的Thread库来实现多线程编程。
下面将介绍C语言中多线程编程的基本概念和用法。
首先,C语言中多线程编程的基本概念是线程。
线程是程序中的一条执行路径,每个线程都有自己的栈空间和寄存器等,可以独立执行不同的任务。
在C语言中,可以使用Thread库中的函数来创建线程、管理线程和同步线程之间的操作。
要在C语言中创建线程,首先需要包含Thread库的头文件,并定义一个函数作为线程的入口点。
然后使用Thread库中的函数创建线程并指定入口点函数,最后启动线程。
例如,下面是一个简单的C语言多线程编程示例:```#include <stdio.h>#include <stdlib.h>#include <pthread.h>void *print_message(void *ptr) {char *message = (char *)ptr;printf("%s\n", message);pthread_exit(NULL);}int main() {pthread_t thread;char *message = "Hello, this is a thread!";pthread_create(&thread, NULL, print_message, (void *)message);pthread_join(thread, NULL);return 0;}```在这个示例中,首先定义了一个print_message函数作为线程的入口点,然后在主函数中创建了一个线程,并指定入口点函数为print_message,最后等待线程执行完毕。
当程序执行时,会输出"Hello, this is a thread!",表示线程成功执行。
C语言多线程编程的基本原理和实战技巧

C语言多线程编程的基本原理和实战技巧随着计算机技术的不断发展,多线程编程在软件开发中变得越来越重要。
多线程编程可以提高程序的执行效率,充分利用多核处理器的优势,同时也能改善用户体验。
C语言作为一种广泛应用的编程语言,也提供了丰富的多线程编程接口和技巧。
一、多线程编程的基本原理多线程编程的基本原理是通过创建多个执行线程来同时执行不同的任务,从而提高程序的并发性和响应性。
在C语言中,我们可以使用pthread库来实现多线程编程。
下面是一个简单的示例代码:```c#include <stdio.h>#include <pthread.h>void* thread_function(void* arg) {printf("Hello from a thread!\n");pthread_exit(NULL);}int main() {pthread_t thread_id;int result = pthread_create(&thread_id, NULL, thread_function, NULL);if (result != 0) {perror("Thread creation failed");return 1;}printf("Hello from the main thread!\n");pthread_join(thread_id, NULL);return 0;}```在上面的代码中,我们创建了一个新的线程,并在该线程中执行thread_function函数。
主线程和新线程可以同时执行不同的任务,并且通过pthread_join函数等待新线程的结束。
二、多线程编程的实战技巧除了基本原理外,还有一些实战技巧可以帮助我们更好地进行多线程编程。
1. 线程同步在多线程编程中,线程之间的并发执行可能会导致数据竞争和不一致的结果。
线程实例实验报告总结

一、实验目的本次实验旨在通过实例操作,深入了解线程的概念、创建、同步与通信机制,以及线程在实际编程中的应用。
通过实验,提高对线程的理解和运用能力,为以后开发多线程程序打下坚实基础。
二、实验环境1. 操作系统:Windows 102. 开发工具:Visual Studio 20193. 编程语言:C#三、实验内容1. 线程的基本概念线程是程序执行的最小单位,是操作系统进行资源分配和调度的基本单位。
线程具有以下特点:(1)线程是轻量级的,创建、销毁线程的开销较小。
(2)线程共享进程的资源,如内存、文件等。
(3)线程之间可以并发执行。
2. 线程的创建在C#中,可以使用以下方式创建线程:(1)使用Thread类```csharpThread thread = new Thread(new ThreadStart(MethodName));thread.Start();```(2)使用lambda表达式```csharpThread thread = new Thread(() => MethodName());thread.Start();```(3)使用匿名方法```csharpThread thread = new Thread(delegate () { MethodName(); });thread.Start();```3. 线程的同步线程同步是指多个线程在执行过程中,为了防止资源冲突而采取的协调机制。
C#提供了以下同步机制:(1)互斥锁(Mutex)```csharpMutex mutex = new Mutex();mutex.WaitOne();// 线程同步代码mutex.ReleaseMutex();```(2)信号量(Semaphore)```csharpSemaphore semaphore = new Semaphore(1, 1);semaphore.WaitOne();// 线程同步代码semaphore.Release();```(3)读写锁(ReaderWriterLock)```csharpReaderWriterLock rwlock = new ReaderWriterLock();rwlock.AcquireReaderLock();// 读取操作rwlock.ReleaseReaderLock();```4. 线程的通信线程通信是指线程之间传递消息、共享数据的过程。
C语言中的多线程编程技术解析

C语言中的多线程编程技术解析在C语言中,多线程编程技术是一种能够提高程序性能和效率的重要手段。
多线程编程使得程序能够同时执行多个任务,从而充分利用多核处理器的优势,加快程序的运行速度。
本文将从多线程的概念、实现方式以及常见应用场景进行解析,帮助读者深入了解C语言中的多线程编程技术。
首先,我们需要了解多线程的概念。
在C语言中,多线程是指在一个程序中可以同时执行多个程序段或函数,每个线程都有自己的执行路径。
与传统的单线程程序相比,多线程程序能够更好地同时处理多个任务,提高程序的并发性和响应速度。
在多线程编程中,通常会涉及线程的创建、启动、暂停、终止以及线程之间的通信等操作。
接着,我们需要了解多线程在C语言中的实现方式。
在C语言中,可以使用标准的POSIX线程库(pthread)来实现多线程编程。
使用pthread库,我们可以轻松创建、启动和管理多个线程。
具体来说,通过pthread_create函数可以创建一个新线程,通过pthread_join函数可以等待一个线程的结束,通过pthread_exit函数可以终止当前线程等。
此外,pthread库还提供了一系列的同步机制,如互斥锁(mutex)、条件变量(condition variable)等,帮助程序员更好地控制线程的并发访问。
在实际应用中,多线程编程技术通常用于处理需要并行处理的任务,比如网络编程、图像处理、数据分析等。
以网络编程为例,当一个服务器需要同时处理多个客户端的请求时,可以为每个客户端连接创建一个独立的线程,从而实现并发处理。
这样不仅提高了服务器的处理能力,也提高了系统的响应速度。
除了提高程序性能外,多线程编程还有助于代码模块化和复用。
通过将不同的功能模块放置在不同的线程中,可以更好地实现代码的分离和聚合,提高程序的可维护性和可扩展性。
此外,多线程编程还有助于充分利用多核处理器的优势,充分发挥硬件资源的性能。
总的来说,C语言中的多线程编程技术是一种重要的程序设计手段,能够提高程序的性能和效率,提高程序的并发性和响应速度。
c#Winform多线程操作

c#Winform多线程操作主要是对⼀个过程需要的时间很长执⾏时会出现界⾯假死的情况⽅法1:Application.DoEvents(),这种⽅法当你拖动窗体时,界⾯不会假死。
但在你拖动时代码不再执⾏,也就是阻塞了,当你不再控制窗体时会继续执⾏,其实这还是⼀个单线程for (int i = 0; i < 10000; i++){for (int j = 0; j < 100000; j++){textBox1.Text = i.ToString() + "" + j.ToString();Application.DoEvents();}}⽅法2:多线程2.1:取消控件跨线程检测(不推荐有时会出现⼀些莫名奇妙的错误如控件不能加载等问题)2.1.1取消窗体内控件的跨线程检查(单个控件取消也可以) public Form1(){InitializeComponent();CheckForIllegalCrossThreadCalls = false;//⼲掉检测不再检测跨线程}2.1.2新建线程实现跨线程访问///<summary>///新建线程并执⾏///</summary>///<param name="sender"></param>///<param name="e"></param>private void button1_Click(object sender, EventArgs e){ThreadStart thStart = new ThreadStart(Pro);//threadStart委托Thread thread = new Thread(thStart);thread.Priority = ThreadPriority.Highest;thread.IsBackground = true; //关闭窗体继续执⾏thread.Start();}public void Pro(){for (int i = 0; i < 10000; i++){for (int j = 0; j < 100000; j++){textBox1.Text = j.ToString();}}}2.2:主线程中操作(推荐) 2.2.1 不⽤取消跨线程访问///<summary>///新建线程并执⾏///</summary>///<param name="sender"></param>///<param name="e"></param>private void button1_Click(object sender, EventArgs e){ThreadStart thStart = new ThreadStart(Pro);//threadStart委托Thread thread = new Thread(thStart);thread.Priority = ThreadPriority.Highest;thread.IsBackground = true; //关闭窗体继续执⾏thread.Start();}public void Pro(){for (int i = 0; i < 10000; i++){for (int j = 0; j < 100000; j++){if (textBox1.InvokeRequired)//不同线程访问了textBox1.Invoke(new Action<TextBox, string>(SetTxtValue), textBox1, j.ToString());//跨线程了else//同线程直接赋值textBox1.Text = j.ToString();}}}private void SetTxtValue(TextBox txt, string value){txt.Text = value;}注:多个线程同时访问⼀个⽅法时需要锁定public static readonly object obj = new object();public void Pro(){//lock(obj){}=Monitor.Enter(obj) Monitor.Exit(obj)lock (obj){for (int i = 0; i < 10000; i++){for (int j = 0; j < 100000; j++){if (textBox1.InvokeRequired)//不同线程访问了textBox1.Invoke(new Action<TextBox, string>(SetTxtValue), textBox1, j.ToString());//跨线程了else//同线程直接赋值textBox1.Text = j.ToString();}}}}3.窗体与⾃定义类之间的多线程操作(适⽤数据量⼤查询速度慢时让数据在新线程中查询防主线程卡死) 3.1⾃定义类中定义事件,并定义各事件执⾏的步骤⽅法3.2窗体中实现类,并⽣成类各事件,在多线程中执⾏⾃定义类的步骤⽅法3.3 代码3.1public class WeiTuo{public int count { get; set; }public event EventHandler StartEvent;public event EventHandler MidEvent;public event EventHandler EndEvent;public event EventHandler EEvent;public void ExecEvent(){try{using (SqlConnection con = new SqlConnection("server=.;uid=sa;pwd=123;database=oa")){using (SqlDataAdapter adp = new SqlDataAdapter("select * from a", con)){DataTable dt = new DataTable();adp.Fill(dt);StartEvent(dt.Rows.Count, null);for (int i = 0; i < dt.Rows.Count; i++){a ai = new a() {ID = (int)dt.Rows[i]["id"],Code = dt.Rows[i]["cCode"].ToString()} ;MidEvent(ai, null);}EndEvent(dt.Rows.Count, null);}}}catch (Exception e){EEvent(e.Message, null);}}}public class a{public int ID { get; set; }public String Code { get; set; } = "";}View Code3.4 代码3.2private void button6_Click(object sender, EventArgs e){WeiTuo wt = new WeiTuo();wt.StartEvent += Wt_StartEvent;wt.MidEvent += Wt_MidEvent;wt.EndEvent += Wt_EndEvent;wt.EEvent += Wt_EEvent;Thread th = new Thread(wt.ExecEvent);th.Start();}//特殊委托 actionprivate void Wt_StartEvent(object sender, EventArgs e){Action<string> setLVItem = (s) => { listView1.Items.Add(s); };this.Invoke(setLVItem, sender.ToString());}//特殊委托 actionprivate void Wt_MidEvent(object sender, EventArgs e){Action<string> setLVItem = (s) => { listView1.Items.Add(s); };this.Invoke(setLVItem, ((a)sender).Code);}#region委托实现private void Wt_EndEvent(object sender, EventArgs e){this.Invoke(new setLVItem(setEndValue), "成功");}delegate void setLVItem(string s);void setEndValue(string s){MessageBox.Show(s);}#endregionprivate void Wt_EEvent(object sender, EventArgs e){Action<string> ShowBox = (s) => { MessageBox.Show(s); };this.Invoke(ShowBox, sender.ToString());}View Code3.5 结果如下图task任务与thread⼤同⼩异使⽤时尽量少的让控件跨线程可通过ref 或 out 对参数传出检测线程结束再给控件赋值也可⽤task的wait⽅法4 异步回调private void button1_Click(object sender, EventArgs e){Func<int, int, int> Sum = (i, j) =>{Thread.Sleep(3000);return i + j;};listView1.Items.Add("开始");IAsyncResult iar = Sum.BeginInvoke(1, 2, CallbackWhenDone, "我是测试");listView1.Items.Add("over");}private void CallbackWhenDone(IAsyncResult iar){AsyncResult ar = (AsyncResult)iar;Func<int, int, int> f = (Func<int, int, int>)ar.AsyncDelegate;Action<ListView> a = (lv) =>{lv.Items.Add(ar.AsyncState.ToString());lv.Items.Add(f.EndInvoke(iar).ToString());};this.Invoke( a,listView1);}View Code。
C语言多线程编程实战经验分享

C语言多线程编程实战经验分享C语言是一种广泛应用于系统编程和嵌入式开发领域的编程语言,具有高效性和灵活性。
在开发过程中,多线程编程是一种常用的技术,能够充分利用多核处理器的优势,提高程序的性能和响应速度。
本文将分享一些C语言多线程编程的实战经验,希望能够帮助读者更好地应用多线程技术。
首先,多线程编程需要注意线程的并发控制。
在多线程环境下,多个线程会同时访问共享的资源,可能会导致数据竞态和死锁等问题。
为了避免这些问题,可以使用互斥锁(mutex)来保护共享资源的访问。
在访问共享资源之前,先加锁,访问完毕后再解锁,确保同一时间只有一个线程可以访问共享资源,从而保证数据的一致性和正确性。
其次,线程间的通信也是多线程编程中需要考虑的重要问题。
线程间可以通过共享内存、消息队列、信号量等机制进行通信。
其中,消息队列是一种常用的通信方式,可以实现生产者和消费者之间的消息传递。
通过使用消息队列,线程之间可以实现解耦,减少直接依赖关系,提高系统的灵活性和可维护性。
另外,线程的同步和异步执行也是多线程编程的关键。
同步执行是指线程按顺序执行,一个线程执行完毕后再执行下一个线程;而异步执行是指线程可以同时执行,不受其他线程的阻塞。
在实际开发中,需要根据具体的需求选择合适的执行方式,以提高程序的效率和性能。
在进行多线程编程时,还需要注意线程的管理和调度。
多线程系统中会存在多个线程,需要合理地管理和调度这些线程,避免出现优先级倒置、饥饿现象等问题。
可以通过设置线程的优先级、调度策略等方式来进行线程的管理,确保系统的稳定性和响应速度。
最后,调试和测试是多线程编程中不可或缺的一步。
由于多线程程序具有一定的复杂性,可能会出现线程死锁、竞态条件等问题,因此需要通过调试和测试来发现和解决这些问题。
可以使用调试工具、日志记录等方式来定位和排查程序中的bug,保证程序的正确性和稳定性。
总之,C语言多线程编程是一项挑战性的任务,需要综合考虑并发控制、线程通信、执行方式、管理调度等方面的问题。
C# WinForm多线程开发

C# WinForm多线程开发一Thread类库Windows是一个多任务的系统,如果你使用的是windows 2000及其以上版本,你可以通过任务管理器查看当前系统运行的程序和进程。
什么是进程呢?当一个程序开始运行时,它就是一个进程,进程所指包括运行中的程序和程序所使用到的内存和系统资源。
而一个进程又是由多个线程所组成的,线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针、程序计数器等),但代码区是共享的,即不同的线程可以执行同样的函数。
多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。
一关于Thread的说明在.net framework class library中,所有与多线程机制应用相关的类都是放在System.Threading 命名空间中的。
其中提供Thread类用于创建线程,ThreadPool类用于管理线程池等等,此外还提供解决了线程执行安排,死锁,线程间通讯等实际问题的机制。
如果你想在你的应用程序中使用多线程,就必须包含这个类。
Thread类有几个至关重要的方法,描述如下:Start():启动线程Sleep(int):静态方法,暂停当前线程指定的毫秒数Abort():通常使用该方法来终止一个线程Suspend():该方法并不终止未完成的线程,它仅仅挂起线程,以后还可恢复。
Resume():恢复被Suspend()方法挂起的线程的执行线程入口使程序知道该让这个线程干什么事,在C#中,线程入口是通过ThreadStart代理(delegate)来提供的,你可以把ThreadStart理解为一个函数指针,指向线程要执行的函数,当调用Thread.Start()方法后,线程就开始执行ThreadStart所代表或者说指向的函数。
ThreadState在各种情况下的可能取值如下:Aborted:线程已停止AbortRequested:线程的Thread.Abort()方法已被调用,但是线程还未停止Background:线程在后台执行,与属性Thread.IsBackground有关Running:线程正在正常运行Stopped:线程已经被停止StopRequested:线程正在被要求停止Suspended:线程已经被挂起(此状态下,可以通过调用Resume()方法重新运行)SuspendRequested:线程正在要求被挂起,但是未来得及响应Unstarted:未调用Thread.Start()开始线程的运行WaitSleepJoin:线程因为调用了Wait(),Sleep()或Join()等方法处于封锁状态二Winform中使用的thread首先可以看看最直接的方法,也是.net 1.0下支持的方法。
c#winform多线程的小例子

c#winform多线程的⼩例⼦在⽂本框中输⼊⼀个数字,点击开始累加按钮,程序计算从1开始累计到该数字的结果。
因为该累加过程⽐较耗时,如果直接在UI线程中进⾏,那么当前窗⼝将出现假死。
为了有更好的⽤户体验,程序启动⼀个新的线程来单独执⾏该计算,然后每隔200毫秒读取⼀次累加结果,并把结果显⽰到⽂本框下⽅的label控件中。
同时,程序⽀持取消操作,点击取消累计按钮,程序将取消累加操作,并把当前累加值显⽰到label中。
为了⽅便后⾯的描述,我把UI线程称作主线程,把执⾏累加计算的线程称作⼯作者线程。
该过程有两个关键点:1:如何在⼯作者线程中访问主线程创建的控件;2:如何取消⽐较耗时的计算;为了便于在⼯作者线程中调⽤累加过程,我把它写成⼀个单独⽅法,如下:复制代码代码如下:/// <summary>/// 从1累加到指定的值,为了让该⽅法⽀持取消操作所以需要CancellationToken参数/// </summary>/// <param name="countTo">累加到的指定值</param>/// <param name="ct">取消凭证</param>private void CountTo(int countTo, CancellationToken ct) {int sum = 0;for (; countTo > 0; countTo--) {if (ct.IsCancellationRequested) {break;}sum += countTo;//Invoke⽅法⽤于获得创建lbl_Status的线程所在的上下⽂this.Invoke(new Action(()=>lbl_Status.Text = sum.ToString()));Thread.Sleep(200);}}该⽅法就是⽤于累加数字,它有两个需要注意的地⽅1:⽅法需要传递⼀个CancellationToken参数,⽤于⽀持取消操作(《clr via c# 3版》中把这种⽅式称作协作式取消,也就是说某⼀个操作必须⽀持取消,然后才能取消该操作);2:为了允许⼯作者线程访问主线程创建的lbl_Status控件,我在该线程中使⽤this.Invoke⽅法。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
C# WinForm多线程开发一Thread类库Windows是一个多任务的系统,如果你使用的是windows 2000及其以上版本,你可以通过任务管理器查看当前系统运行的程序和进程。
什么是进程呢?当一个程序开始运行时,它就是一个进程,进程所指包括运行中的程序和程序所使用到的内存和系统资源。
而一个进程又是由多个线程所组成的,线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针、程序计数器等),但代码区是共享的,即不同的线程可以执行同样的函数。
多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。
一关于Thread的说明在.net framework class library中,所有与多线程机制应用相关的类都是放在System.Threading 命名空间中的。
其中提供Thread类用于创建线程,ThreadPool类用于管理线程池等等,此外还提供解决了线程执行安排,死锁,线程间通讯等实际问题的机制。
如果你想在你的应用程序中使用多线程,就必须包含这个类。
Thread类有几个至关重要的方法,描述如下:Start():启动线程Sleep(int):静态方法,暂停当前线程指定的毫秒数Abort():通常使用该方法来终止一个线程Suspend():该方法并不终止未完成的线程,它仅仅挂起线程,以后还可恢复。
Resume():恢复被Suspend()方法挂起的线程的执行线程入口使程序知道该让这个线程干什么事,在C#中,线程入口是通过ThreadStart代理(delegate)来提供的,你可以把ThreadStart理解为一个函数指针,指向线程要执行的函数,当调用Thread.Start()方法后,线程就开始执行ThreadStart所代表或者说指向的函数。
ThreadState在各种情况下的可能取值如下:Aborted:线程已停止AbortRequested:线程的Thread.Abort()方法已被调用,但是线程还未停止Background:线程在后台执行,与属性Thread.IsBackground有关Running:线程正在正常运行Stopped:线程已经被停止StopRequested:线程正在被要求停止Suspended:线程已经被挂起(此状态下,可以通过调用Resume()方法重新运行)SuspendRequested:线程正在要求被挂起,但是未来得及响应Unstarted:未调用Thread.Start()开始线程的运行WaitSleepJoin:线程因为调用了Wait(),Sleep()或Join()等方法处于封锁状态二Winform中使用的thread首先可以看看最直接的方法,也是.net 1.0下支持的方法。
但请注意的是,此方法在.net 2.0以后就已经是一种错误的方法了。
[csharp] view plain copy 在CODE上查看代码片派生到我的代码片public partial class Form1 : Form{public Form1(){InitializeComponent();}private void Form1_Load(object sender, EventArgs e){Thread thread = new Thread(ThreadFuntion);thread.IsBackground = true;thread.Start();}private void ThreadFuntion(){while (true){this.textBox1.Text = DateTime.Now.ToString();Thread.Sleep(1000);}}}这段code 在vs2005或者2008上都抛出异常:Cross-thread operation not valid:Control 'textBox1' accessed from a thread other than the thread it was created on . 这是因为.net 2.0以后加强了安全机制,不允许在winform中直接跨线程访问控件的属性。
那么怎么解决这个问题呢,下面提供几种方案。
第一种方案:在Thread创建之气,将Control.CheckForIllegalCrossThreadCalls 设为false。
此代码告诉编译器:在这个类中我们不检查跨线程的调用是否合法(如果没有加这句话运行也没有异常,那么说明系统以及默认的采用了不检查的方式)。
然而,这种方法不可取。
我们查看CheckForIllegalCrossThreadCalls 这个属性的定义,就会发现它是一个static的,也就是说无论我们在项目的什么地方修改了这个值,他就会在全局起作用。
而且像这种跨线程访问是否存在异常,我们通常都会去检查。
如果项目中其他人修改了这个属性,那么我们的方案就失败了,我们要采取另外的方案。
第二种方案[csharp] view plain copy 在CODE上查看代码片派生到我的代码片namespace TestInvoker{public partial class Form1 : Form{public Form1(){InitializeComponent();}private void button1_Click(object sender, EventArgs e){Thread thread = new Thread(new ThreadStart(StartSomeWorkFromUIThread));thread.IsBackground = true;thread.Start();//StartSomeWorkFromUIThread();//label1.Text = "Set value through another thread!";}private void StartSomeWorkFromUIThread(){if (this.InvokeRequired){BeginInvoke(new EventHandler(RunsOnWorkerThread), null);}else{RunsOnWorkerThread(this, null);}}private void RunsOnWorkerThread(object sender, EventArgs e){Thread.Sleep(2000);label1.Text = System.DateTime.Now.ToString();}}}通过上叙代码,可以看到问题已经被解决了,通过等待异步,我们就不会总是持有主线程的控制,这样就可以在不发生跨线程调用异常的情况下完成多线程对winform多线程控件的控制了。
二ThreadPool 与Timer本文接上文,继续探讨WinForm中的多线程问题,再次主要探讨threadpool 和timer。
一、ThreadPool线程池(ThreadPool)是一种相对较简单的方法,它适应于一些需要多个线程而又较短任务(如一些常处于阻塞状态的线程),它的缺点是对创建的线程不能加以控制,也不能设置其优先级。
由于每个进程只有一个线程池,当然每个应用程序域也只有一个线程池(对线),所以你将发现ThreadPool类的成员函数都为static!当你首次调用ThreadPool.QueueUserWorkItem、ThreadPool.RegisterWaitForSingleObject等,便会创建线程池实例。
下面我就线程池当中的两函数作一介绍:[csharp] view plain copy 在CODE上查看代码片派生到我的代码片public static bool QueueUserWorkItem( //调用成功则返回trueWaitCallback callBack,//要创建的线程调用的委托object state //传递给委托的参数)//它的另一个重载函数类似,只是委托不带参数而已此函数的作用是把要创建的线程排队到线程池,当线程池的可用线程数不为零时(线程池有创建线程数的限制,缺身值为25),便创建此线程,否则就排队到线程池等到它有可用的线程时才创建。
[csharp] view plain copy 在CODE上查看代码片派生到我的代码片public static RegisteredWaitHandle RegisterWaitForSingleObject(WaitHandle waitObject,// 要注册的WaitHandleWaitOrTimerCallback callBack,// 线程调用的委托object state,//传递给委托的参数int TimeOut,//超时,单位为毫秒,bool executeOnlyOnce //是否只执行一次);public delegate void WaitOrTimerCallback(object state,//也即传递给委托的参数bool timedOut//true表示由于超时调用,反之则因为waitObject);此函数的作用是创建一个等待线程,一旦调用此函数便创建此线程,在参数waitObject变为终止状态或所设定的时间TimeOut到了之前,它都处于“阻塞”状态,值得注意的一点是此“阻塞”与Thread的WaitSleepJoin状态有很大的不同:当某Thread处于WaitSleepJoin 状态时CPU会定期的唤醒它以轮询更新状态信息,然后再次进入WaitSleepJoin状态,线程的切换可是很费资源的;而用此函数创建的线程则不同,在触发它运行之前,CPU不会切换到此线程,它既不占用CPU的时间又不浪费线程切换时间,但CPU又如何知道何时运行它?实际上线程池会生成一些辅助线程用来监视这些触发条件,一旦达到条件便启动相应的线程,当然这些辅助线程本身也占用时间,但是如果你需创建较多的等待线程时,使用线程池的优势就越加明显。
更详细内容demo:[csharp] view plain copy 在CODE上查看代码片派生到我的代码片namespace TestMethodInvoker{public partial class Form2 : Form{public Form2(){InitializeComponent();}private void button1_Click(object sender, EventArgs e){//ThreadPool.RegisterWaitForSingleObject(// ev,// new WaitOrTimerCallback(WaitThreadFunc),// 4,// 2000,// false//表示每次完成等待操作后都重置计时器,直到注销等待// );ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadFunc), "test1");//Thread.Sleep(10000);}private delegate void MyInvokeDelegate(string name);private void Test(object o){richTextBox1.Text += string.Format("the object is {0} \n", o);}public void ThreadFunc(object b){this.Invoke(new MyInvokeDelegate(Test), b);}public void WaitThreadFunc(object b, bool t){richTextBox1.Text += string.Format("the object is {0},t is {1}\n", b, t);}}}一个很值得扩展的地方时,这里的invoke 用的是代理,其实还有其他的方法,比如action 和func。