[C# 线程处理系列]专题三:线程池中的工作者线程
2015-11-04 11:34
666 查看
/article/1642816.html
目录:
一、CLR线程池基础
二、通过线程池的工作者线程实现异步
三、使用委托实现异步
四、任务
一、线程池基础
首先,创建和销毁线程是一个要耗费大量时间的过程,另外,太多的线程也会浪费内存资源,所以通过Thread类来创建过多的线程反而有损于性能,为了改善这样的问题 ,.net中就引入了线程池。
线程池形象的表示就是存放应用程序中使用的线程的一个集合(就是放线程的地方,这样线程都放在一个地方就好管理了)。CLR初始化时,线程池中是没有线程的,在内部, 线程池维护了一个操作请求队列,当应用程序想执行一个异步操作时,就调用一个方法,就将一个任务放到线程池的队列中,线程池中代码从队列中提取任务,将这个任务委派给一个线程池线程去执行,当线程池线程完成任务时,线程不会被销毁,而是返回到线程池中,等待响应另一个请求。由于线程不被销毁, 这样就可以避免因为创建线程所产生的性能损失。
注意:通过线程池创建的线程默认为后台线程,优先级默认为Normal.
二、通过线程池的工作者线程实现异步
3.1 创建工作者线程的方法
public static bool QueueUserWorkItem (WaitCallback callBack);
public static bool QueueUserWorkItem(WaitCallback callback, Object state);
这两个方法向线程池的队列添加一个工作项(work item)以及一个可选的状态数据。然后,这两个方法就会立即返回。
工作项其实就是由callback参数标识的一个方法,该方法将由线程池线程执行。同时写的回调方法必须匹配System.Threading.WaitCallback委托类型,定义为:
public delegate void WaitCallback(Object state);
下面演示如何通过线程池线程来实现异步调用:
[csharp] view
plaincopyprint?
using System;
using System.Threading;
namespace ThreadPoolUse
{
class Program
{
static void Main(string[] args)
{
// 设置线程池中处于活动的线程的最大数目
// 设置线程池中工作者线程数量为1000,I/O线程数量为1000
ThreadPool.SetMaxThreads(1000, 1000);
Console.WriteLine("Main Thread: queue an asynchronous method");
PrintMessage("Main Thread Start");
// 把工作项添加到队列中,此时线程池会用工作者线程去执行回调方法
ThreadPool.QueueUserWorkItem(asyncMethod);
Console.Read();
}
// 方法必须匹配WaitCallback委托
private static void asyncMethod(object state)
{
Thread.Sleep(1000);
PrintMessage("Asynchoronous Method");
Console.WriteLine("Asynchoronous thread has worked ");
}
// 打印线程池信息
private static void PrintMessage(String data)
{
int workthreadnumber;
int iothreadnumber;
// 获得线程池中可用的线程,把获得的可用工作者线程数量赋给workthreadnumber变量
// 获得的可用I/O线程数量给iothreadnumber变量
ThreadPool.GetAvailableThreads(out workthreadnumber, out iothreadnumber);
Console.WriteLine("{0}\n CurrentThreadId is {1}\n CurrentThread is background :{2}\n WorkerThreadNumber is:{3}\n IOThreadNumbers is: {4}\n",
data,
Thread.CurrentThread.ManagedThreadId,
Thread.CurrentThread.IsBackground.ToString(),
workthreadnumber.ToString(),
iothreadnumber.ToString());
}
}
}
运行结果:
从结果中可以看出,线程池中的可用的工作者线程少了一个,用去执行回调方法了。
ThreadPool.QueueUserWorkItem(WaitCallback callback,Object state) 方法可以把object对象作为参数传送到回调函数中,使用和ThreadPool.QueueUserWorkItem(WaitCallback callback)的使用和类似,这里就不列出了。
3.2 协作式取消
.net Framework提供了取消操作的模式, 这个模式是协作式的。为了取消一个操作,首先必须创建一个System.Threading.CancellationTokenSource对象。
下面代码演示了协作式取消的使用,主要实现当用户在控制台敲下回车键后就停止数数方法。
[csharp] view
plaincopyprint?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
ThreadPool.SetMaxThreads(1000, 1000);
Console.WriteLine("Main thread run");
PrintMessage("Start");
Run();
Console.ReadKey();
}
private static void Run()
{
CancellationTokenSource cts = new CancellationTokenSource();
// 这里用Lambda表达式的方式和使用委托的效果一样的,只是用了Lambda后可以少定义一个方法。
// 这在这里就是让大家明白怎么lambda表达式如何由委托转变的
////ThreadPool.QueueUserWorkItem(o => Count(cts.Token, 1000));
ThreadPool.QueueUserWorkItem(callback, cts.Token);
Console.WriteLine("Press Enter key to cancel the operation\n");
Console.ReadLine();
// 传达取消请求
cts.Cancel();
}
private static void callback(object state)
{
Thread.Sleep(1000);
PrintMessage("Asynchoronous Method Start");
CancellationToken token =(CancellationToken)state;
Count(token, 1000);
}
// 执行的操作,当受到取消请求时停止数数
private static void Count(CancellationToken token,int countto)
{
for (int i = 0; i < countto; i++)
{
if (token.IsCancellationRequested)
{
Console.WriteLine("Count is canceled");
break;
}
Console.WriteLine(i);
Thread.Sleep(300);
}
Console.WriteLine("Cout has done");
}
// 打印线程池信息
private static void PrintMessage(String data)
{
int workthreadnumber;
int iothreadnumber;
// 获得线程池中可用的线程,把获得的可用工作者线程数量赋给workthreadnumber变量
// 获得的可用I/O线程数量给iothreadnumber变量
ThreadPool.GetAvailableThreads(out workthreadnumber, out iothreadnumber);
Console.WriteLine("{0}\n CurrentThreadId is {1}\n CurrentThread is background :{2}\n WorkerThreadNumber is:{3}\n IOThreadNumbers is: {4}\n",
data,
Thread.CurrentThread.ManagedThreadId,
Thread.CurrentThread.IsBackground.ToString(),
workthreadnumber.ToString(),
iothreadnumber.ToString());
}
}
}
运行结果:
四、使用委托实现异步
通过调用ThreadPool的QueueUserWorkItem方法来来启动工作者线程非常方便,但委托WaitCallback指向的是带有一个参数的无返回值的方法,如果我们实际操作中需要有返回值,或者需要带有多个参数, 这时通过这样的方式就难以实现, 为了解决这样的问题,我们可以通过委托来建立工作这线程,
下面代码演示了使用委托如何实现异步:
[csharp] view
plaincopyprint?
using System;
using System.Threading;
namespace Delegate
{
class Program
{
// 使用委托的实现的方式是使用了异步变成模型APM(Asynchronous Programming Model)
// 自定义委托
private delegate string MyTestdelegate();
static void Main(string[] args)
{
ThreadPool.SetMaxThreads(1000, 1000);
PrintMessage("Main Thread Start");
//实例化委托
MyTestdelegate testdelegate = new MyTestdelegate(asyncMethod);
// 异步调用委托
IAsyncResult result = testdelegate.BeginInvoke(null, null);
// 获取结果并打印出来
string returndata = testdelegate.EndInvoke(result);
Console.WriteLine(returndata);
Console.ReadLine();
}
private static string asyncMethod()
{
Thread.Sleep(1000);
PrintMessage("Asynchoronous Method");
return "Method has completed";
}
// 打印线程池信息
private static void PrintMessage(String data)
{
int workthreadnumber;
int iothreadnumber;
// 获得线程池中可用的线程,把获得的可用工作者线程数量赋给workthreadnumber变量
// 获得的可用I/O线程数量给iothreadnumber变量
ThreadPool.GetAvailableThreads(out workthreadnumber, out iothreadnumber);
Console.WriteLine("{0}\n CurrentThreadId is {1}\n CurrentThread is background :{2}\n WorkerThreadNumber is:{3}\n IOThreadNumbers is: {4}\n",
data,
Thread.CurrentThread.ManagedThreadId,
Thread.CurrentThread.IsBackground.ToString(),
workthreadnumber.ToString(),
iothreadnumber.ToString());
}
}
}
运行结果:
五、任务
同样 任务的引入也是为了解决通过ThreadPool.QueueUserWorkItem中限制的问题,
下面代码演示通过任务来实现异步:
5.1 使用任务来实现异步
[csharp] view
plaincopyprint?
using System;
using System.Threading;
using System.Threading.Tasks;
namespace TaskUse
{
class Program
{
static void Main(string[] args)
{
ThreadPool.SetMaxThreads(1000, 1000);
PrintMessage("Main Thread Start");
// 调用构造函数创建Task对象,
Task<int> task = new Task<int>(n => asyncMethod((int)n), 10);
// 启动任务
task.Start();
// 等待任务完成
task.Wait();
Console.WriteLine("The Method result is: "+task.Result);
Console.ReadLine();
}
private static int asyncMethod(int n)
{
Thread.Sleep(1000);
PrintMessage("Asynchoronous Method");
int sum = 0;
for (int i = 1; i < n; i++)
{
// 如果n太大,使用checked使下面代码抛出异常
checked
{
sum += i;
}
}
return sum;
}
// 打印线程池信息
private static void PrintMessage(String data)
{
int workthreadnumber;
int iothreadnumber;
// 获得线程池中可用的线程,把获得的可用工作者线程数量赋给workthreadnumber变量
// 获得的可用I/O线程数量给iothreadnumber变量
ThreadPool.GetAvailableThreads(out workthreadnumber, out iothreadnumber);
Console.WriteLine("{0}\n CurrentThreadId is {1}\n CurrentThread is background :{2}\n WorkerThreadNumber is:{3}\n IOThreadNumbers is: {4}\n",
data,
Thread.CurrentThread.ManagedThreadId,
Thread.CurrentThread.IsBackground.ToString(),
workthreadnumber.ToString(),
iothreadnumber.ToString());
}
}
}
运行结果:
5.2 取消任务
如果要取消任务, 同样可以使用一个CancellationTokenSource对象来取消一个Task.
下面代码演示了如何来取消一个任务:
[csharp] view
plaincopyprint?
using System;
using System.Threading;
using System.Threading.Tasks;
namespace TaskUse
{
class Program
{
static void Main(string[] args)
{
ThreadPool.SetMaxThreads(1000, 1000);
PrintMessage("Main Thread Start");
CancellationTokenSource cts = new CancellationTokenSource();
// 调用构造函数创建Task对象,将一个CancellationToken传给Task构造器从而使Task和CancellationToken关联起来
Task<int> task = new Task<int>(n => asyncMethod(cts.Token, (int)n), 10);
// 启动任务
task.Start();
// 延迟取消任务
Thread.Sleep(3000);
// 取消任务
cts.Cancel();
Console.WriteLine("The Method result is: " + task.Result);
Console.ReadLine();
}
private static int asyncMethod(CancellationToken ct, int n)
{
Thread.Sleep(1000);
PrintMessage("Asynchoronous Method");
int sum = 0;
try
{
for (int i = 1; i < n; i++)
{
// 当CancellationTokenSource对象调用Cancel方法时,
// 就会引起OperationCanceledException异常
// 通过调用CancellationToken的ThrowIfCancellationRequested方法来定时检查操作是否已经取消,
// 这个方法和CancellationToken的IsCancellationRequested属性类似
ct.ThrowIfCancellationRequested();
Thread.Sleep(500);
// 如果n太大,使用checked使下面代码抛出异常
checked
{
sum += i;
}
}
}
catch (Exception e)
{
Console.WriteLine("Exception is:" + e.GetType().Name);
Console.WriteLine("Operation is Canceled");
}
return sum;
}
// 打印线程池信息
private static void PrintMessage(String data)
{
int workthreadnumber;
int iothreadnumber;
// 获得线程池中可用的线程,把获得的可用工作者线程数量赋给workthreadnumber变量
// 获得的可用I/O线程数量给iothreadnumber变量
ThreadPool.GetAvailableThreads(out workthreadnumber, out iothreadnumber);
Console.WriteLine("{0}\n CurrentThreadId is {1}\n CurrentThread is background :{2}\n WorkerThreadNumber is:{3}\n IOThreadNumbers is: {4}\n",
data,
Thread.CurrentThread.ManagedThreadId,
Thread.CurrentThread.IsBackground.ToString(),
workthreadnumber.ToString(),
iothreadnumber.ToString());
}
}
}
运行结果:
5.3 任务工厂
同样可以通过任务工厂TaskFactory类型来实现异步操作。
[csharp] view
plaincopyprint?
using System;
using System.Threading;
using System.Threading.Tasks;
namespace TaskFactory
{
class Program
{
static void Main(string[] args)
{
ThreadPool.SetMaxThreads(1000, 1000);
Task.Factory.StartNew(() => PrintMessage("Main Thread"));
Console.Read();
}
// 打印线程池信息
private static void PrintMessage(String data)
{
int workthreadnumber;
int iothreadnumber;
// 获得线程池中可用的线程,把获得的可用工作者线程数量赋给workthreadnumber变量
// 获得的可用I/O线程数量给iothreadnumber变量
ThreadPool.GetAvailableThreads(out workthreadnumber, out iothreadnumber);
Console.WriteLine("{0}\n CurrentThreadId is {1}\n CurrentThread is background :{2}\n WorkerThreadNumber is:{3}\n IOThreadNumbers is: {4}\n",
data,
Thread.CurrentThread.ManagedThreadId,
Thread.CurrentThread.IsBackground.ToString(),
workthreadnumber.ToString(),
iothreadnumber.ToString());
}
}
}
运行结果:
讲到这里CLR的工作者线程大致讲完了,希望也篇文章可以让大家对线程又有进一步的理解。在后面的一篇线程系列将谈谈CLR线程池的I/O线程。
版权声明:本文为博主原创文章,未经博主允许不得转载。
目录:
一、CLR线程池基础
二、通过线程池的工作者线程实现异步
三、使用委托实现异步
四、任务
一、线程池基础
首先,创建和销毁线程是一个要耗费大量时间的过程,另外,太多的线程也会浪费内存资源,所以通过Thread类来创建过多的线程反而有损于性能,为了改善这样的问题 ,.net中就引入了线程池。
线程池形象的表示就是存放应用程序中使用的线程的一个集合(就是放线程的地方,这样线程都放在一个地方就好管理了)。CLR初始化时,线程池中是没有线程的,在内部, 线程池维护了一个操作请求队列,当应用程序想执行一个异步操作时,就调用一个方法,就将一个任务放到线程池的队列中,线程池中代码从队列中提取任务,将这个任务委派给一个线程池线程去执行,当线程池线程完成任务时,线程不会被销毁,而是返回到线程池中,等待响应另一个请求。由于线程不被销毁, 这样就可以避免因为创建线程所产生的性能损失。
注意:通过线程池创建的线程默认为后台线程,优先级默认为Normal.
二、通过线程池的工作者线程实现异步
3.1 创建工作者线程的方法
public static bool QueueUserWorkItem (WaitCallback callBack);
public static bool QueueUserWorkItem(WaitCallback callback, Object state);
这两个方法向线程池的队列添加一个工作项(work item)以及一个可选的状态数据。然后,这两个方法就会立即返回。
工作项其实就是由callback参数标识的一个方法,该方法将由线程池线程执行。同时写的回调方法必须匹配System.Threading.WaitCallback委托类型,定义为:
public delegate void WaitCallback(Object state);
下面演示如何通过线程池线程来实现异步调用:
[csharp] view
plaincopyprint?
using System;
using System.Threading;
namespace ThreadPoolUse
{
class Program
{
static void Main(string[] args)
{
// 设置线程池中处于活动的线程的最大数目
// 设置线程池中工作者线程数量为1000,I/O线程数量为1000
ThreadPool.SetMaxThreads(1000, 1000);
Console.WriteLine("Main Thread: queue an asynchronous method");
PrintMessage("Main Thread Start");
// 把工作项添加到队列中,此时线程池会用工作者线程去执行回调方法
ThreadPool.QueueUserWorkItem(asyncMethod);
Console.Read();
}
// 方法必须匹配WaitCallback委托
private static void asyncMethod(object state)
{
Thread.Sleep(1000);
PrintMessage("Asynchoronous Method");
Console.WriteLine("Asynchoronous thread has worked ");
}
// 打印线程池信息
private static void PrintMessage(String data)
{
int workthreadnumber;
int iothreadnumber;
// 获得线程池中可用的线程,把获得的可用工作者线程数量赋给workthreadnumber变量
// 获得的可用I/O线程数量给iothreadnumber变量
ThreadPool.GetAvailableThreads(out workthreadnumber, out iothreadnumber);
Console.WriteLine("{0}\n CurrentThreadId is {1}\n CurrentThread is background :{2}\n WorkerThreadNumber is:{3}\n IOThreadNumbers is: {4}\n",
data,
Thread.CurrentThread.ManagedThreadId,
Thread.CurrentThread.IsBackground.ToString(),
workthreadnumber.ToString(),
iothreadnumber.ToString());
}
}
}
运行结果:
从结果中可以看出,线程池中的可用的工作者线程少了一个,用去执行回调方法了。
ThreadPool.QueueUserWorkItem(WaitCallback callback,Object state) 方法可以把object对象作为参数传送到回调函数中,使用和ThreadPool.QueueUserWorkItem(WaitCallback callback)的使用和类似,这里就不列出了。
3.2 协作式取消
.net Framework提供了取消操作的模式, 这个模式是协作式的。为了取消一个操作,首先必须创建一个System.Threading.CancellationTokenSource对象。
下面代码演示了协作式取消的使用,主要实现当用户在控制台敲下回车键后就停止数数方法。
[csharp] view
plaincopyprint?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
ThreadPool.SetMaxThreads(1000, 1000);
Console.WriteLine("Main thread run");
PrintMessage("Start");
Run();
Console.ReadKey();
}
private static void Run()
{
CancellationTokenSource cts = new CancellationTokenSource();
// 这里用Lambda表达式的方式和使用委托的效果一样的,只是用了Lambda后可以少定义一个方法。
// 这在这里就是让大家明白怎么lambda表达式如何由委托转变的
////ThreadPool.QueueUserWorkItem(o => Count(cts.Token, 1000));
ThreadPool.QueueUserWorkItem(callback, cts.Token);
Console.WriteLine("Press Enter key to cancel the operation\n");
Console.ReadLine();
// 传达取消请求
cts.Cancel();
}
private static void callback(object state)
{
Thread.Sleep(1000);
PrintMessage("Asynchoronous Method Start");
CancellationToken token =(CancellationToken)state;
Count(token, 1000);
}
// 执行的操作,当受到取消请求时停止数数
private static void Count(CancellationToken token,int countto)
{
for (int i = 0; i < countto; i++)
{
if (token.IsCancellationRequested)
{
Console.WriteLine("Count is canceled");
break;
}
Console.WriteLine(i);
Thread.Sleep(300);
}
Console.WriteLine("Cout has done");
}
// 打印线程池信息
private static void PrintMessage(String data)
{
int workthreadnumber;
int iothreadnumber;
// 获得线程池中可用的线程,把获得的可用工作者线程数量赋给workthreadnumber变量
// 获得的可用I/O线程数量给iothreadnumber变量
ThreadPool.GetAvailableThreads(out workthreadnumber, out iothreadnumber);
Console.WriteLine("{0}\n CurrentThreadId is {1}\n CurrentThread is background :{2}\n WorkerThreadNumber is:{3}\n IOThreadNumbers is: {4}\n",
data,
Thread.CurrentThread.ManagedThreadId,
Thread.CurrentThread.IsBackground.ToString(),
workthreadnumber.ToString(),
iothreadnumber.ToString());
}
}
}
运行结果:
四、使用委托实现异步
通过调用ThreadPool的QueueUserWorkItem方法来来启动工作者线程非常方便,但委托WaitCallback指向的是带有一个参数的无返回值的方法,如果我们实际操作中需要有返回值,或者需要带有多个参数, 这时通过这样的方式就难以实现, 为了解决这样的问题,我们可以通过委托来建立工作这线程,
下面代码演示了使用委托如何实现异步:
[csharp] view
plaincopyprint?
using System;
using System.Threading;
namespace Delegate
{
class Program
{
// 使用委托的实现的方式是使用了异步变成模型APM(Asynchronous Programming Model)
// 自定义委托
private delegate string MyTestdelegate();
static void Main(string[] args)
{
ThreadPool.SetMaxThreads(1000, 1000);
PrintMessage("Main Thread Start");
//实例化委托
MyTestdelegate testdelegate = new MyTestdelegate(asyncMethod);
// 异步调用委托
IAsyncResult result = testdelegate.BeginInvoke(null, null);
// 获取结果并打印出来
string returndata = testdelegate.EndInvoke(result);
Console.WriteLine(returndata);
Console.ReadLine();
}
private static string asyncMethod()
{
Thread.Sleep(1000);
PrintMessage("Asynchoronous Method");
return "Method has completed";
}
// 打印线程池信息
private static void PrintMessage(String data)
{
int workthreadnumber;
int iothreadnumber;
// 获得线程池中可用的线程,把获得的可用工作者线程数量赋给workthreadnumber变量
// 获得的可用I/O线程数量给iothreadnumber变量
ThreadPool.GetAvailableThreads(out workthreadnumber, out iothreadnumber);
Console.WriteLine("{0}\n CurrentThreadId is {1}\n CurrentThread is background :{2}\n WorkerThreadNumber is:{3}\n IOThreadNumbers is: {4}\n",
data,
Thread.CurrentThread.ManagedThreadId,
Thread.CurrentThread.IsBackground.ToString(),
workthreadnumber.ToString(),
iothreadnumber.ToString());
}
}
}
运行结果:
五、任务
同样 任务的引入也是为了解决通过ThreadPool.QueueUserWorkItem中限制的问题,
下面代码演示通过任务来实现异步:
5.1 使用任务来实现异步
[csharp] view
plaincopyprint?
using System;
using System.Threading;
using System.Threading.Tasks;
namespace TaskUse
{
class Program
{
static void Main(string[] args)
{
ThreadPool.SetMaxThreads(1000, 1000);
PrintMessage("Main Thread Start");
// 调用构造函数创建Task对象,
Task<int> task = new Task<int>(n => asyncMethod((int)n), 10);
// 启动任务
task.Start();
// 等待任务完成
task.Wait();
Console.WriteLine("The Method result is: "+task.Result);
Console.ReadLine();
}
private static int asyncMethod(int n)
{
Thread.Sleep(1000);
PrintMessage("Asynchoronous Method");
int sum = 0;
for (int i = 1; i < n; i++)
{
// 如果n太大,使用checked使下面代码抛出异常
checked
{
sum += i;
}
}
return sum;
}
// 打印线程池信息
private static void PrintMessage(String data)
{
int workthreadnumber;
int iothreadnumber;
// 获得线程池中可用的线程,把获得的可用工作者线程数量赋给workthreadnumber变量
// 获得的可用I/O线程数量给iothreadnumber变量
ThreadPool.GetAvailableThreads(out workthreadnumber, out iothreadnumber);
Console.WriteLine("{0}\n CurrentThreadId is {1}\n CurrentThread is background :{2}\n WorkerThreadNumber is:{3}\n IOThreadNumbers is: {4}\n",
data,
Thread.CurrentThread.ManagedThreadId,
Thread.CurrentThread.IsBackground.ToString(),
workthreadnumber.ToString(),
iothreadnumber.ToString());
}
}
}
运行结果:
5.2 取消任务
如果要取消任务, 同样可以使用一个CancellationTokenSource对象来取消一个Task.
下面代码演示了如何来取消一个任务:
[csharp] view
plaincopyprint?
using System;
using System.Threading;
using System.Threading.Tasks;
namespace TaskUse
{
class Program
{
static void Main(string[] args)
{
ThreadPool.SetMaxThreads(1000, 1000);
PrintMessage("Main Thread Start");
CancellationTokenSource cts = new CancellationTokenSource();
// 调用构造函数创建Task对象,将一个CancellationToken传给Task构造器从而使Task和CancellationToken关联起来
Task<int> task = new Task<int>(n => asyncMethod(cts.Token, (int)n), 10);
// 启动任务
task.Start();
// 延迟取消任务
Thread.Sleep(3000);
// 取消任务
cts.Cancel();
Console.WriteLine("The Method result is: " + task.Result);
Console.ReadLine();
}
private static int asyncMethod(CancellationToken ct, int n)
{
Thread.Sleep(1000);
PrintMessage("Asynchoronous Method");
int sum = 0;
try
{
for (int i = 1; i < n; i++)
{
// 当CancellationTokenSource对象调用Cancel方法时,
// 就会引起OperationCanceledException异常
// 通过调用CancellationToken的ThrowIfCancellationRequested方法来定时检查操作是否已经取消,
// 这个方法和CancellationToken的IsCancellationRequested属性类似
ct.ThrowIfCancellationRequested();
Thread.Sleep(500);
// 如果n太大,使用checked使下面代码抛出异常
checked
{
sum += i;
}
}
}
catch (Exception e)
{
Console.WriteLine("Exception is:" + e.GetType().Name);
Console.WriteLine("Operation is Canceled");
}
return sum;
}
// 打印线程池信息
private static void PrintMessage(String data)
{
int workthreadnumber;
int iothreadnumber;
// 获得线程池中可用的线程,把获得的可用工作者线程数量赋给workthreadnumber变量
// 获得的可用I/O线程数量给iothreadnumber变量
ThreadPool.GetAvailableThreads(out workthreadnumber, out iothreadnumber);
Console.WriteLine("{0}\n CurrentThreadId is {1}\n CurrentThread is background :{2}\n WorkerThreadNumber is:{3}\n IOThreadNumbers is: {4}\n",
data,
Thread.CurrentThread.ManagedThreadId,
Thread.CurrentThread.IsBackground.ToString(),
workthreadnumber.ToString(),
iothreadnumber.ToString());
}
}
}
运行结果:
5.3 任务工厂
同样可以通过任务工厂TaskFactory类型来实现异步操作。
[csharp] view
plaincopyprint?
using System;
using System.Threading;
using System.Threading.Tasks;
namespace TaskFactory
{
class Program
{
static void Main(string[] args)
{
ThreadPool.SetMaxThreads(1000, 1000);
Task.Factory.StartNew(() => PrintMessage("Main Thread"));
Console.Read();
}
// 打印线程池信息
private static void PrintMessage(String data)
{
int workthreadnumber;
int iothreadnumber;
// 获得线程池中可用的线程,把获得的可用工作者线程数量赋给workthreadnumber变量
// 获得的可用I/O线程数量给iothreadnumber变量
ThreadPool.GetAvailableThreads(out workthreadnumber, out iothreadnumber);
Console.WriteLine("{0}\n CurrentThreadId is {1}\n CurrentThread is background :{2}\n WorkerThreadNumber is:{3}\n IOThreadNumbers is: {4}\n",
data,
Thread.CurrentThread.ManagedThreadId,
Thread.CurrentThread.IsBackground.ToString(),
workthreadnumber.ToString(),
iothreadnumber.ToString());
}
}
}
运行结果:
讲到这里CLR的工作者线程大致讲完了,希望也篇文章可以让大家对线程又有进一步的理解。在后面的一篇线程系列将谈谈CLR线程池的I/O线程。
版权声明:本文为博主原创文章,未经博主允许不得转载。
相关文章推荐
- VS2010 C# Activex
- .Net项目实战2管理员界面充值的功能
- c# 拖动窗体
- C# 扩展方法
- Csharp日常笔记
- Csharp日常笔记
- 利用C#进行Socket通信编程之二:一个实例
- C#[Serializable]在C#中的作用-NET 中的对象序列化
- C# 读取文件
- 《解析C#类中的构造函数》
- 微软XSD工具根据XSD文件生成的C#类中多余Specified属性问题
- C#中ToString()格式详解
- 对于NPOI的一些使用心得(c#)
- C#多线程编程
- C#指定斑马打印机名称来打印,不区分并口,USB等
- C#通过并口连接斑马打印机
- AutoCAD.Net/C#.Net QQ群:193522571 AutoCAD中写状态栏status bar
- C# 制作软件启动画面
- C#构造函数
- DirectX 3D Mesh类