回顾:
1. 通信使用AutoResetEvent类,AutoResetEvent用于通知正在等待线程已发生事件,允许线程通过发信号相互通信。
2. 使用IAsyncResult接口来获取线程执行的结果。这其中又分别用到IAsyncResult自己的一个属性,AsyncWaitHandle等待句柄,异步回调三种方式。
主要内容:
1. 线程池
为什么要使用线程池?
1. 降低物理资料开销
2. 减少因频繁创建或消毁线程对系统的影响
3. 便利集中利用资源或共享一段存储空间
ThreadPool
1. 线程池内的线程默认为后台线程
2. 线程池通过ThreadPool类来实现
3. 请求线程池中的一个线程,需要使用QueueUserWorkItem方法
注意:当向线程池中的线程提交任务后是无法取消的,且线程池中的每个线程均是按默认的优先级运行。
WaitCallBack
1. 向线程提交任务使用WaitCallBack委托,即只需要向QueueUserWorkItem方法传递一个WaitCallBack委托的实例就可以向线程池添加一个任务。线程池针对该任务自动调用一个线程来处理。WaitCallBack委托的原型:
public delegate viod WaitCallBack(object state);
注意:1. 向线程提交的方法必须是WaitCallBack委托型的
2. 参数state就是主线程传递给处理线程的参数,利用这个参数可以实现主线程与子线程之间的简单通信
设置线程池
说明:通常将计算机密集型的操作放在线程池中运行,而线程池的大小会根据当前的CPU使用量自动调整,如:
ThreadPool.SetMaxThreads(10,200);
ThreadPool.SetMinThreads(2,40);
注意:两参数分别是WorkThread和IO Thread的限制。即,辅助线程数目和异步IO线程的数目。
线程使用限制:
1. 它是后台线程
2. 它不能被修改为前台线程
3. 它被提交任务后是不能取消的
4. 它的优先级不或名称不能被设置
5. 对于COM对象大多为多线程单元
6. 线程池中的线程只适合用于时间需求短的任务
如果需要长时间运行,请使用单线程,如:word中的拼写检查器线程
2. BackgroundWorker组件
1. 适用于需要长时间运行的任务,且不影响前台其它功能的使用。
2. 异步执行长时间作业操作
3. 使用时是后台执行辅助方法
4. 调用RunWorkAsync方法
5. 任务完成时触发RunWorkCompleted事件
5. 取消线程
下面是个WINFORM的
1. 通信使用AutoResetEvent类,AutoResetEvent用于通知正在等待线程已发生事件,允许线程通过发信号相互通信。
2. 使用IAsyncResult接口来获取线程执行的结果。这其中又分别用到IAsyncResult自己的一个属性,AsyncWaitHandle等待句柄,异步回调三种方式。
主要内容:
1. 线程池
为什么要使用线程池?
1. 降低物理资料开销
2. 减少因频繁创建或消毁线程对系统的影响
3. 便利集中利用资源或共享一段存储空间
ThreadPool
1. 线程池内的线程默认为后台线程
2. 线程池通过ThreadPool类来实现
3. 请求线程池中的一个线程,需要使用QueueUserWorkItem方法
注意:当向线程池中的线程提交任务后是无法取消的,且线程池中的每个线程均是按默认的优先级运行。
WaitCallBack
1. 向线程提交任务使用WaitCallBack委托,即只需要向QueueUserWorkItem方法传递一个WaitCallBack委托的实例就可以向线程池添加一个任务。线程池针对该任务自动调用一个线程来处理。WaitCallBack委托的原型:
public delegate viod WaitCallBack(object state);
注意:1. 向线程提交的方法必须是WaitCallBack委托型的
2. 参数state就是主线程传递给处理线程的参数,利用这个参数可以实现主线程与子线程之间的简单通信
设置线程池
说明:通常将计算机密集型的操作放在线程池中运行,而线程池的大小会根据当前的CPU使用量自动调整,如:
ThreadPool.SetMaxThreads(10,200);
ThreadPool.SetMinThreads(2,40);
注意:两参数分别是WorkThread和IO Thread的限制。即,辅助线程数目和异步IO线程的数目。
线程使用限制:
1. 它是后台线程
2. 它不能被修改为前台线程
3. 它被提交任务后是不能取消的
4. 它的优先级不或名称不能被设置
5. 对于COM对象大多为多线程单元
6. 线程池中的线程只适合用于时间需求短的任务
如果需要长时间运行,请使用单线程,如:word中的拼写检查器线程
2. BackgroundWorker组件
1. 适用于需要长时间运行的任务,且不影响前台其它功能的使用。
2. 异步执行长时间作业操作
3. 使用时是后台执行辅助方法
4. 调用RunWorkAsync方法
5. 任务完成时触发RunWorkCompleted事件
3. 常用类成员
5. 取消线程
6. 激活进度功能
这一节讲完,基础知识就没有了,先前看完一遍做了一个小工具给公司财务用了(虽说BUG不断,但好呆咱也都找到并解决了,只是代码写的冗余太大,层次都没分),觉着基础不扎实,又重新来了一遍,应该不会再来第三遍了,哈哈。这不做了这么多的笔记,也不是白做的,就是防着以后忘。回头看实例,多多少少应该能有点用。这一遍看的彻底了,理解程序少说也有八成了吧,还真不敢说有九成。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace Con44
{
class Program
{
static void Main(string[] args)
{
int fzThreads;//定义辅助线程数目
int ioAsyncThreads;//定义异步IO线程数目
//ThreadPool.SetMaxThreads(100, 200);//手动设置辅助线程与异步IO线程的数目的最大值
//ThreadPool.SetMinThreads(10, 20);//最小值
//也可以从系统中获取这两从此参数的值
ThreadPool.GetMaxThreads(out fzThreads, out ioAsyncThreads);//获取两参数的最大值
//ThreadPool.GetMinThreads(out fzThreads, out ioAsyncThreads);//获取最小值
//打印系统自动分配的辅助线程和异步IO线程的最大值
Console.WriteLine("辅助线程和的最大数目:{0},异步IO线程的最大数目:{1}",fzThreads,ioAsyncThreads);
for (int i = 0; i < 10; i++)
{
ThreadPool.QueueUserWorkItem(testThreadPool);//传递任务
}
Console.ReadKey();
}
public static void testThreadPool(object state)
{
for (int i = 0; i < 3; i++)
{
Console.WriteLine("辅助线程标识为:{0}---------第{1}次运行。",Thread.CurrentThread.ManagedThreadId,i);
Thread.Sleep(50);
}
}
}
}
下面是个WINFORM的
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace WF44
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
/// <summary>
/// 开始计算
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnCalc_Click(object sender, EventArgs e)
{
btnCalc.Enabled = false;//禁用计算按钮
tb_result.Text = "";//清空结果
btnCancel.Enabled = true;//启用取消按钮
progressBar1.Value = 0;//进度条清0
//此刻启动后台线程,传递一个类对象
try
{
backgroundWorker1.RunWorkerAsync(new calcTest(int.Parse(tb_x.Text), int.Parse(tb_y.Text)));
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
/// <summary>
/// 操作开始时,在另一个线程上运行的处理程序
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
//通过DoWorkEventArgs类型的参数e的Argument属性得到参数对象的实例
calcTest cal = (calcTest)e.Argument;
//模拟一个执行时间
for (int i = 0; i < 3; i++)
{
cal.X += cal.Y;
Thread.Sleep(300);//阻塞0.3秒
if (backgroundWorker1.CancellationPending)
{
e.Cancel = true;
return;
}
}
//将结果传给参数e的result属性
e.Result = cal.X;
}
/// <summary>
/// 当异步线程执行完成时触发RunWorkerCompleted方法
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
tb_result.Text = "已经取消计算操作";
else
//将RunWorkerCompletedEventArgs参数e中的Result交给结果文本框
tb_result.Text = e.Result.ToString();
btnCalc.Enabled = true;
btnCancel.Enabled = false;
//设置进度条的值为100
progressBar1.Value = 100;
}
/// <summary>
/// 取消计算
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnCancel_Click(object sender, EventArgs e)
{
//取消挂起的后台操作
backgroundWorker1.CancelAsync();
}
}
public class calcTest
{
int x;//一个整数
int y;//另一个整数
public int X
{
get { return x; }
set { x = value; }
}
public int Y
{
get { return y; }
set { y = value; }
}
public calcTest(int a, int b)
{
this.x = a;
this.y = b;
}
}
}