- 任务是架构在线程之上的,也就是说任务最终还是要抛给线程去执行。
-
任务跟线程不是一对一的关系,比如开10个任务并不是说会开10个线程,这一点任务有点类似线程池,但是任务相比线程池有很小 的开销和精确的控制。
一:Task
1. 最简单的使用
开启task有两种方式:
<1> 实例化Task
//第一种方式开启
var task1 = new Task(() =>
{
Run1();
});
<2>从工厂中创建
var task2 = Task.Factory.StartNew(() =>
{
Run2();
});
2. 取消任务
在4.0中给我们提供一个“取消标记”叫做CancellationTokenSource.Token,在创建task的时候传入此参数,就可以将主线程和任务相关联,然后在任务中设置“取消信号“叫做ThrowIfCancellationRequested来等待主线程使用Cancel来通知,一旦cancel被调用。task将会抛出OperationCanceledException来中断此任务的执行,最后将当前task的Status的IsCanceled属性设为true。
class Program
{
static void Main(string[] args)
{
CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken ct = cts.Token;
Task task1 = new Task(() => { Run1(ct); }, ct);
Task task2 = new Task(Run2);
try
{
task1.Start();
task2.Start();
Thread.Sleep(1000);
cts.Cancel();
Task.WaitAll(task1, task2);
}
catch (AggregateException ex)
{
foreach(var e in ex.InnerExceptions)
{
Console.WriteLine("\nhi,我是OperationCanceledException:{0}\n", e.Message);
}
Console.WriteLine("task1是不是被取消了? {0}", task1.IsCanceled);
Console.WriteLine("task2是不是被取消了? {0}", task2.IsCanceled);
}
Console.Read();
}
private static void Run1(CancellationToken ct)
{
ct.ThrowIfCancellationRequested();
Console.WriteLine("我是任务1");
Thread.Sleep(2000);
ct.ThrowIfCancellationRequested();
Console.WriteLine("我是任务1的第二部分信息");
}
private static void Run2()
{
Console.WriteLine("我是任务2");
}
}
①:Run1中的Console.WriteLine("我是任务1的第二部分信息"); 没有被执行。
②:Console.WriteLine("task1是不是被取消了? {0}", task1.IsCanceled); 状态为True。
3. 获取任务的返回值
static void Main(string[] args)
{
var t1 = Task.Factory.StartNew<List<string>>(() => { return Run1(); });
t1.Wait();
var t2 = Task.Factory.StartNew(() =>
{
Console.WriteLine("t1集合中返回的个数:" + string.Join(",", t1.Result));
});
Console.Read();
}
private static List<string> Run1()
{
return new List<string> { "1", "4", "8" };
}
<2>采用ContinueWith方法
static void Main(string[] args)
{
var t1 = Task.Factory.StartNew<List<string>>(() => { return Run1(); });
t1.Wait();
var t2 = t1.ContinueWith((i) =>
{
Console.WriteLine("t1集合中返回的个数:" + string.Join(",", i.Result));
});
Console.Read();
}
private static List<string> Run1()
{
return new List<string> { "1", "4", "8" };
}
4:ContinueWith结合WaitAll
static void Main(string[] args)
{
ConcurrentStack<int> stack = new ConcurrentStack<int>();
//t1先串行
var t1 = Task.Factory.StartNew(() =>
{
stack.Push(1);
stack.Push(2);
});
//t2,t3并行执行
var t2 = t1.ContinueWith(t =>
{
int result;
stack.TryPop(out result);
});
//t2,t3并行执行
var t3 = t1.ContinueWith(t =>
{
int result;
stack.TryPop(out result);
});
//等待t2和t3执行完
Task.WaitAll(t2, t3);
//t4先串行
var t4 = Task.Factory.StartNew(() =>
{
stack.Push(1);
stack.Push(2);
});
//t5,t6并行执行
var t5 = t4.ContinueWith(t =>
{
int result;
stack.TryPop(out result);
});
//t5,t6并行执行
var t6 = t4.ContinueWith(t =>
{
int result;
//只弹出,不移除
stack.TryPeek(out result);
});
//临界区:等待t5,t6执行完
Task.WaitAll(t5, t6);
var t7 = Task.Factory.StartNew(() =>
{
Console.WriteLine("当前集合元素个数:" + stack.Count);
});
Console.Read();
}