Chapter3 ThreadPool

花费极少的时间来完成创建很多异步操作。

每个短暂的异步操作 创建线程都会产生显著开销。

线程池可以成功地是应用任何需要大量短暂的开销大情形。

事先 分配一定的资源,将这些资源放入到资源池。每次需要新的资源,只需从线程池 或许一个,而不用创建一个新的。

当该资源不再被使用时,就将其放回到池中。

每个CLR 都有一个线程池实例。

ThreadPool 类型拥有一个 QueueUserWorkerItem 静态方法,该静态方法接受一个委托,代表用户自定义的一个异步操作。

在该方法调用后,委托会进入一个内部队列中。

如果线程池中没有任何线程,将创建一个新的工作线程,并将队列中第一个委托放入该工作线程中。

如果线程池中放入新的操作,当之前的所有操作完成后,很可能只需重用一个线程来执行这些新操作。

然而,如果放置新的操作过快,线程池将创建更多的线程来执行这些操作。

创建太多的线程是有限的,在这种情况下新的操作将在队列中等待,直到工作线程有能力来执行他们。

保持线程池中的操作都是短暂的,并且非常重要的。不要在线程池中放入长时间运行的操作,或者阻塞工作线程。

这将导致所有线程变得繁忙,从而无法服务用户操作。

当停止向线程池中放入新操作时,线程池最终会删掉一定时间后过期不在使用的线程。这将释放那别不再需要的系统资源。

必须执行运行时间短的操作。

减少并行度耗费 和 节省系统资源。

ASP.NET 中只推荐使用输入/输出密集型异步操作,因为其使用了一个不同的方式,就做I/O线程

线程池中的线程都是后台线程。当所有的前台线程完成后,所有的后台线程将停止工作




线程池中调用委托:

IAsyncResult:  表示异步操作的状态

IAsyncResult.AsyncState: 获取用户定义的对象,它限定或包含关于异步操作的信息。

定义一个委托并使用beginInvoke来调用该委托,BeginInvoke 接受一个回调函数。

回调函数在异步操作完成后会被调用,并且 一个用户自定义的状态会传给该回调函数。该状态通常用来区分异步调用。

最后,我们得到一个实现了IAsyncResult接口的result对象,beginInvoke立即返回i了结果,当线程池中的工作线程在执行异步操作时,仍允许我们继续其他工作。当需要异步操作结果时,可以使用BeginInvoke方法调用返回的result对象。我们可以使用result对象的IsCompleted属性轮询结果。

但这块,使用了 AsyncWaitHandle属性来等待直到操作完成。当操作完成后,会得到一个结果,可以通过委托调用EndInvoke方法,将 IAsyncResult 对象传递个委托参数。

当操作完成后,传递给BeginInvoke方法的回调函数将被放置到线程池中,确切的说是一个工作线程中,如果将 Main方法结尾的TreadSleep 注释掉,那么回调函数将不会执行,因为当主线程完成后,所有后台线程将被停止,包括该回调函数

将委托和回调函数的异步调用很可能会被同一个工作线程执行。

使用BeginOperationName/EndOperationName 方法和 .NET中的IAsyncResult对象等方式称为异步编程模型APM,这样的方法称为异步方法。

现代编程中,更推荐使用任务并行库。

using System;
using System.Threading;
namespace ThreadPools
{
class Program
{
private delegate string RunOnThreadPool(out int threadId);


private static void CallBack(IAsyncResult art)
{
Console.WriteLine("Starting a callback...");
Console.WriteLine("state passed to a call back: {0}", art.AsyncState);
Console.WriteLine("Is Thread Pool : {0}", Thread.CurrentThread.IsThreadPoolThread);
Console.WriteLine("Thread pool worker thread id : {0}", Thread.CurrentThread.ManagedThreadId);
}


private static string Test(out int ThreadId)
{
Console.WriteLine("Starting...");
Console.WriteLine("Is Thread pool thread: {0}", Thread.CurrentThread.IsThreadPoolThread);
Thread.Sleep(TimeSpan.FromSeconds(2));
ThreadId = Thread.CurrentThread.ManagedThreadId;
return string.Format("Thread pool wprker id is {0}", ThreadId);
}
static void Main(string[] args)
{
int threadId = 0;
RunOnThreadPool poolDelegate = Test;
var t = new Thread(() => Test(out threadId));
t.Start();
t.Join();


Console.WriteLine("Thread id : {0}", threadId);
IAsyncResult r = poolDelegate.BeginInvoke(out threadId, CallBack, "a delegate asynchronous call"); //传给callback的参数
r.AsyncWaitHandle.WaitOne();
string result = poolDelegate.EndInvoke(out threadId, r);   //返回委托所绑定的函数的返回结果
Console.WriteLine("Thread pool worker thread id :{0}", threadId);
Console.WriteLine("result of begininvoke is {0}",result);
Thread.Sleep(TimeSpan.FromMinutes(5));



}
}
}

该状态通常用来区分异步调用

向线程池中放入异步调用

线程池并行度:

实现一个取消选项:

在线程池中使用等事件处理器及超时:

使用计时器:

使用BackGroundWorker 组件:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值