|
.NET:如何让线程支持超时?
MS 现在不推荐使用低级别的 Thread 编程,而推荐使用 Task.
如何让线程支持超时? 下面介绍三种方法
方法一:使用 CancellationTokenSource(需要.net framework 4.5)
方法二:使用 Join
方法三:基于 Task 的实现
方法一:使用 CancellationTokenSource
private static void TimeoutTest1()
{
var cts = new CancellationTokenSource();
var thread = new Thread(() =>
{
Console.WriteLine(String.Format("线程{0}执行中", Thread.CurrentThread.ManagedThreadId));
Thread.Sleep(10000);
Console.WriteLine(String.Format("线程{0}执行中", Thread.CurrentThread.ManagedThreadId));
});
cts.Token.Register(() =>
{
thread.Abort();
});
cts.CancelAfter(1000);
thread.Start();
thread.Join();
Console.WriteLine(String.Format("线程{0}的状态:{1}", thread.ManagedThreadId, thread.ThreadState));
}
输出
备注 这里采用了 Abort 终止了线程,CancellationTokenSource 也支持其它模式,可以去官方看看文档。
方法二:使用 Join
private static void TimeoutTest2()
{
var thread = new Thread(() =>
{
Console.WriteLine(String.Format("线程{0}执行中", Thread.CurrentThread.ManagedThreadId));
Thread.Sleep(10000);
Console.WriteLine(String.Format("线程{0}执行中", Thread.CurrentThread.ManagedThreadId));
});
thread.Start();
thread.Join(1000);
thread.Abort();
Console.WriteLine(String.Format("线程{0}的状态:{1}", thread.ManagedThreadId, thread.ThreadState));
}
输出
方法三:基于 Task 的实现
private static void TimeoutTest3() { var cts = new CancellationTokenSource(); var task = new Task(() => { while (true) { cts.Token.ThrowIfCancellationRequested();
Console.WriteLine("xxxxxx"); Thread.Sleep(1000); } }, cts.Token);
task.Start();
cts.CancelAfter(5000);
Console.ReadLine(); }
输出
如何让线程在执行结束后销毁?线程执行完、遇到未处理异常和被终止后就自动不可用了,如果是垃圾,自然会被 GC 给回收,有一点需要说明的是:线程的未处理异常会导致应用程序的终止,一个线程的异常不会自动冒泡到其它线程。 备注我学习多线程知识感觉到的一个好处就是:让我对数据库并发有了更深刻的认识了,找个机会写写线程的乐观锁和数据库的乐观锁的比较,思路基本一样。
框架地址:http://happy.codeplex.com
原文来自:http://www.cnblogs.com/happyframework/p/3440877.html;
BeginInvoke、ThreadPool、Task三类异步方法的区别和速度比较
| 速度(最快为1) | 返回值 | 多参数 | 等待在时限内完成 | 超时后结束 | ThreadPool.UnsafeQueueUserWorkItem() | 1 | 非原生支持1 | 非原生支持 | 非原生支持3 | 不支持 | ThreadPool.QueueUserWorkItem() | 2.7 | 非原生支持1 | 非原生支持 | 非原生支持3 | 不支持 | Task() | 4.5 | 支持2 | 非原生支持 | 支持 | 自愿结束 | Delegate.BeinInvoke() | 25.4 | 非原生支持1 | 支持 | 支持4 | 不支持 | Thread.Start() | 11009 | 非原生支持1 | 非原生支持 | 非原生支持3 | 支持 |
如ThreadPool.UnsafeQueueUserWorkItem(()=>result=Add(1,2)); 用Task<> 里面在程序末尾EventWaitHandle.Set(),外面WaitOne(TimeSpan)。 获得BeginInvoke的返回值asyncResult,再调asyncResult.AsyncWaitHandle.WaitOne(); 有图有真相。这是各种异步方法循环调用N次所需的时间。
注意,上面BeginInvoke的用法并不完整,应当再调用EndInvoke。但是鉴于BeginInvoke已经最慢了,EndInvoke便不加了。
所以,如果无需返回值,一般就用ThreadPool吧,要更多控制,就Task。鄙人想不到用BeginInvoke的时机。
参考 代码:
static void Main(string[] args)
{
Action threadStart = (() => { });
WaitCallback waitCallback = new WaitCallback(a => { });
Stopwatch stopWatch = new Stopwatch();
stopWatch.Reset();
stopWatch.Start();
for (int i = 0; i < 10000; i++)
{
System.Threading.ThreadPool.UnsafeQueueUserWorkItem(waitCallback, null);
}
stopWatch.Stop();
Console.WriteLine("{0,-40}{1}", "ThreadPool.UnsafeQueueUserWorkItem():", stopWatch.ElapsedTicks);
GC.Collect();
stopWatch.Reset();
stopWatch.Start();
for (int i = 0; i < 10000; i++)
{
System.Threading.ThreadPool.QueueUserWorkItem(waitCallback);
}
stopWatch.Stop();
Console.WriteLine("{0,-40}{1}", "ThreadPool.QueueUserWorkItem():", stopWatch.ElapsedTicks);
GC.Collect();
stopWatch.Reset();
stopWatch.Start();
for (int i = 0; i < 10000; i++)
{
Task t = new Task(threadStart);
t.Start();
}
stopWatch.Stop();
Console.WriteLine("{0,-40}{1}", "Task():", stopWatch.ElapsedTicks);
GC.Collect();
stopWatch.Reset();
stopWatch.Start();
for (int i = 0; i < 10000; i++)
{
threadStart.BeginInvoke(null, null);
}
stopWatch.Stop();
Console.WriteLine("{0,-40}{1}", "Delegate.BeinInvoke():", stopWatch.ElapsedTicks);
}
|
|
|