概念
Task
是一个管理并行工作单元的轻量对象,相当于ThreadPool
。处于命名空间System.Threading.Tasks
下。
使用
- 创建和执行任务
有两种方式创建,一种是调用Task.Run()
,另一种是使用Task.Factory.StartNew()
。
如下示例:
Task t1 = Task.Run(() =>
{
Console.WriteLine("第一个任务");
});
Task t2 = Task.Factory.StartNew(() =>
{
Console.WriteLine("第二个任务");
});
- 等待一个或多个任务完成
无条件等待任务完成:使用Task.Wait()
等待一个任务完成,调用改方法会一直阻塞线程,直到该任务完成。
Task t1 = Task.Run(() =>
{
Thread.Sleep(500);
Console.WriteLine("第一个任务");
});
Console.WriteLine($"t1.Status:{t1.Status}"); // t1.Status:WaitingToRun
t1.Wait(); //无条件等待t1完成
Console.WriteLine($"t1.Status:{t1.Status}"); // t1.Status:RanToCompletion
有条件等待任务完成:使用Task.Wait(Int32)
或者Task.Wait(TimeSpan)
阻塞线程,等待任务完成或者时间间隔结束。
Task t1 = Task.Run(() =>
{
Thread.Sleep(500);
Console.WriteLine("第一个任务");
});
Console.WriteLine($"t1.Status:{t1.Status}");
t1.Wait(100);
bool completed = t1.IsCompleted;
Console.WriteLine($"t1 completed:{completed},t1.Status:{t1.Status}");
if (!completed)
{
Console.WriteLine("t1任务完成前时间已结束");
}
//output:
//t1.Status:WaitingToRun
//t1 completed:False,t1.Status:Running
//t1任务完成前时间已结束
- 取消任务
使用CancelationToken
取消令牌可以对Task做取消操作
static void Main(string[] args)
{
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
CancellationToken cancellationToken = cancellationTokenSource.Token;
Task t1 = Task.Run(() =>
{
Thread.Sleep(1000);
Console.WriteLine("第一个任务");
});
Task t2 = Task.Factory.StartNew(() =>
{
Thread.Sleep(500);
RunMethod(cancellationToken);
Console.WriteLine("第二个任务");
},cancellationToken);
//Thread.Sleep(2000)
cancellationTokenSource.Cancel();
Task.WaitAll(t1, t2);
}
private static void RunMethod(CancellationToken cancellationToken)
{
Console.WriteLine("进入 取消任务的测试方法");
cancellationToken.ThrowIfCancellationRequested();
Console.WriteLine("结束 取消任务的测试方法");
}
//output:
// 进入 取消任务的测试方法
// 第一个任务
//如果Thread.Sleep(2000):
// 进入 取消任务的测试方法
// 结束 取消任务的测试方法
// 第二个任务
// 第一个任务
- 异常处理
基本异常处理:
Task t1 = Task.Run(() =>
{
Console.WriteLine("第一个任务");
});
Task t2 = Task.Factory.StartNew(() =>
{
Console.WriteLine("第二个任务");
});
Task t3 = Task.Run(() =>
{
throw new DivideByZeroException();
});
try
{
Task.WaitAll(t1, t2, t3);
}
catch (AggregateException ex)
{
foreach (var inner in ex.InnerExceptions)
{
Console.WriteLine(inner.Message);
}
}
使用迭代的异常处理Handler:
当我们需要哪些异常需要处理,哪些异常需要向上传递,System.AggregateException
提供了一个Handle()
方法来处理AggregateException
中的每一个异常,返回true,则表示异常已处理,不用抛出,返回false,抛出异常
Task t1 = Task.Run(() =>
{
Console.WriteLine("第一个任务");
});
Task t2 = Task.Factory.StartNew(() =>
{
Console.WriteLine("第二个任务");
});
Task t3 = Task.Run(() =>
{
throw new DivideByZeroException();
});
try
{
Task.WaitAll(t1, t2, t3);
}
catch (AggregateException ex)
{
ex.Handle((inner) =>
{
if (inner is OperationCanceledException)
{
return true;
}
else
{
return false;
}
});
}
源码:
https://github.com/zhaobingwang/Demo/tree/master/TaskDemo
参考
MSDN:Task
博客园-吾爱易逝:.Net4.0 任务(Task)
.NET 并行(多核)编程系列之五 Task执行和异常处理