深入分析C# Task
Task的MSDN的描述如下:
【Task类的表示单个操作不会返回一个值,通常以异步方式执行。
Task对象是一种的中心思想基于任务的异步模式首次引入.NETFramework4中。
因为由执行工作Task对象通常以异步方式执行线程池线程上而不是以同步方式在主应用程序线程中,可以使用Status属性,并将IsCanceled,IsCompleted,和IsFaulted属性,以确定任务的状态。
大多数情况下,lambda表达式用于指定该任务所执行的工作量。
对于返回值的操作,您使用Task类。】
1、Task的优势
ThreadPool相比Thread来说具备了很多优势,但是ThreadPool却又存在一些使用上的不方便。比如:
- ThreadPool不支持线程的取消、完成、失败通知等交互性操作;
- ThreadPool不支持线程执行的先后次序;
以往,如果开发者要实现上述功能,需要完成很多额外的工作,现在,FCL中提供了一个功能更强大的概念:Task。Task在线程池的基础上进行了优化,并提供了更多的API。在FCL4.0中,如果我们要编写多线程程序,Task显然已经优于传统的方式。
以下是一个简单的任务示例:
usingSystem;
usingSystem.Threading;
usingSystem.Threading.Tasks;
namespaceConsoleApp1
{
classProgram
{
staticvoidMain(string[]args)
{
Taskt=newTask(()=>
{
Console.WriteLine("任务开始工作……");
//模拟工作过程
Thread.Sleep(5000);
});
t.Start();
t.ContinueWith((task)=>
{
Console.WriteLine("任务完成,完成时候的状态为:");
Console.WriteLine("IsCanceled={0}\tIsCompleted={1}\tIsFaulted={2}",task.IsCanceled,task.IsCompleted,task.IsFaulted);
});
Console.ReadKey();
}
}
}
2、Task的用法
2.1、创建任务
(一)无返回值的方式
方式1:
vart1=newTask(()=>TaskMethod("Task1"));
t1.Start();
Task.WaitAll(t1);//等待所有任务结束
注:任务的状态:
Start之前为:Created
Start之后为:WaitingToRun
方式2:
Task.Run(()=>TaskMethod("Task2"));
方式3:
Task.Factory.StartNew(()=>TaskMethod("Task3"));直接异步的方法
//或者
vart3=Task.Factory.StartNew(()=>TaskMethod("Task3"));
Task.WaitAll(t3);//等待所有任务结束
//任务的状态:
Start之前为:Running
Start之后为:Running
usingSystem;
usingSystem.Threading;
usingSystem.Threading.Tasks;
namespaceConsoleApp1
{
classProgram
{
staticvoidMain(string[]args)
{
vart1=newTask(()=>TaskMethod("Task1"));
vart2=newTask(()=>TaskMethod("Task2"));
t2.Start();
t1.Start();
Task.WaitAll(t1,t2);
Task.Run(()=>TaskMethod("Task3"));
Task.Factory.StartNew(()=>TaskMethod("Task4"));
//标记为长时间运行任务,则任务不会使用线程池,而在单独的线程中运行。
Task.Factory.StartNew(()=>TaskMethod("Task5"),TaskCreationOptions.LongRunning);
#region常规的使用方式
Console.WriteLine("主线程执行业务处理.");
//创建任务
Tasktask=newTask(()=>
{
Console.WriteLine("使用System.Threading.Tasks.Task执行异步操作.");
for(inti=0;i<10;i++)
{
Console.WriteLine(i);
}
});
//启动任务,并安排到当前任务队列线程中执行任务(System.Threading.Tasks.TaskScheduler)
task.Start();
Console.WriteLine("主线程执行其他处理");
task.Wait();
#endregion
Thread.Sleep(TimeSpan.FromSeconds(1));
Console.ReadLine();
}
staticvoidTaskMethod(stringname)
{
Console.WriteLine("Task{0}isrunningonathreadid{1}.Isthreadpoolthread:{2}",
name,Thread.CurrentThread.ManagedThreadId,Thread.CurrentThread.IsThreadPoolThread);
}
}
}
async/await的实现方式:
usingSystem;
usingSystem.Threading;
usingSystem.Threading.Tasks;
namespaceConsoleApp1
{
classProgram
{
asyncstaticvoidAsyncFunction()
{
awaitTask.Delay(1);
Console.WriteLine("使用System.Threading.Tasks.Task执行异步操作.");
for(inti=0;i<10;i++)
{
Console.WriteLine(string.Format("AsyncFunction:i={0}",i));
}
}
publicstaticvoidMain()
{
Console.WriteLine("主线程执行业务处理.");
AsyncFunction();
Console.WriteLine("主线程执行其他处理");
for(inti=0;i<10;i++)
{
Console.WriteLine(string.Format("Main:i={0}",i));
}
Console.ReadLine();
}
}
}
(二)带返回值的方式
方式4:
Tasktask=CreateTask("Task1"); task.Start(); intresult=task.Result;
usingSystem;
usingSystem.Threading;
usingSystem.Threading.Tasks;
namespaceConsoleApp1
{
classProgram
{
staticTaskCreateTask(stringname)
{
returnnewTask(()=>TaskMethod(name));
}
staticvoidMain(string[]args)
{
TaskMethod("MainThreadTask");
Tasktask=CreateTask("Task1");
task.Start();
intresult=task.Result;
Console.WriteLine("Task1Resultis:{0}",result);
task=CreateTask("Task2");
//该任务会运行在主线程中
task.RunSynchronously();
result=task.Result;
Console.WriteLine("Task2Resultis:{0}",result);
task=CreateTask("Task3");
Console.WriteLine(task.Status);
task.Start();
while(!task.IsCompleted)
{
Console.WriteLine(task.Status);
Thread.Sleep(TimeSpan.FromSeconds(0.5));
}
Console.WriteLine(task.Status);
result=task.Result;
Console.WriteLine("Task3Resultis:{0}",result);
#region常规使用方式
//创建任务
Taskgetsumtask=newTask(()=>Getsum());
//启动任务,并安排到当前任务队列线程中执行任务(System.Threading.Tasks.TaskScheduler)
getsumtask.Start();
Console.WriteLine("主线程执行其他处理");
//等待任务的完成执行过程。
getsumtask.Wait();
//获得任务的执行结果
Console.WriteLine("任务执行结果:{0}",getsumtask.Result.ToString());
#endregion
}
staticintTaskMethod(stringname)
{
Console.WriteLine("Task{0}isrunningonathreadid{1}.Isthreadpoolthread:{2}",
name,Thread.CurrentThread.ManagedThreadId,Thread.CurrentThread.IsThreadPoolThread);
Thread.Sleep(TimeSpan.FromSeconds(2));
return42;
}
staticintGetsum()
{
intsum=0;
Console.WriteLine("使用Task执行异步操作.");
for(inti=0;i<100;i++)
{
sum+=i;
}
returnsum;
}
}
}
async/await的实现:
usingSystem;
usingSystem.Threading.Tasks;
namespaceConsoleApp1
{
classProgram
{
publicstaticvoidMain()
{
varret1=AsyncGetsum();
Console.WriteLine("主线程执行其他处理");
for(inti=1;i<=3;i++)
Console.WriteLine("CallMain()");
intresult=ret1.Result;//阻塞主线程
Console.WriteLine("任务执行结果:{0}",result);
}
asyncstaticTaskAsyncGetsum()
{
awaitTask.Delay(1);
intsum=0;
Console.WriteLine("使用Task执行异步操作.");
for(inti=0;i<100;i++)
{
sum+=i;
}
returnsum;
}
}
}
2.2、组合任务.ContinueWith
简单Demo:
usingSystem;
usingSystem.Threading.Tasks;
namespaceConsoleApp1
{
classProgram
{
publicstaticvoidMain()
{
//创建一个任务
Tasktask=newTask(()=>
{
intsum=0;
Console.WriteLine("使用Task执行异步操作.");
for(inti=0;i<100;i++)
{
sum+=i;
}
returnsum;
});
//启动任务,并安排到当前任务队列线程中执行任务(System.Threading.Tasks.TaskScheduler)
task.Start();
Console.WriteLine("主线程执行其他处理");
//任务完成时执行处理。
Taskcwt=task.ContinueWith(t=>
{
Console.WriteLine("任务完成后的执行结果:{0}",t.Result.ToString());
});
task.Wait();
cwt.Wait();
}
}
}
任务的串行:
usingSystem;
usingSystem.Collections.Concurrent;
usingSystem.Threading;
usingSystem.Threading.Tasks;
namespaceConsoleApp1
{
classProgram
{
staticvoidMain(string[]args)
{
ConcurrentStackstack=newConcurrentStack();
//t1先串行
vart1=Task.Factory.StartNew(()=>
{
stack.Push(1);
stack.Push(2);
});
//t2,t3并行执行
vart2=t1.ContinueWith(t=>
{
intresult;
stack.TryPop(outresult);
Console.WriteLine("Taskt2result={0},Threadid{1}",result,Thread.CurrentThread.ManagedThreadId);
});
//t2,t3并行执行
vart3=t1.ContinueWith(t=>
{
intresult;
stack.TryPop(outresult);
Console.WriteLine("Taskt3result={0},Threadid{1}",result,Thread.CurrentThread.ManagedThreadId);
});
//等待t2和t3执行完
Task.WaitAll(t2,t3);
//t7串行执行
vart4=Task.Factory.StartNew(()=>
{
Console.WriteLine("当前集合元素个数:{0},Threadid{1}",stack.Count,Thread.CurrentThread.ManagedThreadId);
});
t4.Wait();
}
}
}
子任务:
usingSystem;
usingSystem.Threading.Tasks;
namespaceConsoleApp1
{
classProgram
{
publicstaticvoidMain()
{
Taskparent=newTask(state=>
{
Console.WriteLine(state);
string[]result=newstring[2];
//创建并启动子任务
newTask(()=>{result[0]="我是子任务1。";},TaskCreationOptions.AttachedToParent).Start();
newTask(()=>{result[1]="我是子任务2。";},TaskCreationOptions.AttachedToParent).Start();
returnresult;
},"我是父任务,并在我的处理过程中创建多个子任务,所有子任务完成以后我才会结束执行。");
//任务处理完成后执行的操作
parent.ContinueWith(t=>
{
Array.ForEach(t.Result,r=>Console.WriteLine(r));
});
//启动父任务
parent.Start();
//等待任务结束Wait只能等待父线程结束,没办法等到父线程的ContinueWith结束
//parent.Wait();
Console.ReadLine();
}
}
}
动态并行(TaskCreationOptions.AttachedToParent)父任务等待所有子任务完成后整个任务才算完成
usingSystem;
usingSystem.Threading;
usingSystem.Threading.Tasks;
namespaceConsoleApp1
{
classNode
{
publicNodeLeft{get;set;}
publicNodeRight{get;set;}
publicstringText{get;set;}
}
classProgram
{
staticNodeGetNode()
{
Noderoot=newNode
{
Left=newNode
{
Left=newNode
{
Text="L-L"
},
Right=newNode
{
Text="L-R"
},
Text="L"
},
Right=newNode
{
Left=newNode
{
Text="R-L"
},
Right=newNode
{
Text="R-R"
},
Text="R"
},
Text="Root"
};
returnroot;
}
staticvoidMain(string[]args)
{
Noderoot=GetNode();
DisplayTree(root);
}
staticvoidDisplayTree(Noderoot)
{
vartask=Task.Factory.StartNew(()=>DisplayNode(root),
CancellationToken.None,
TaskCreationOptions.None,
TaskScheduler.Default);
task.Wait();
}
staticvoidDisplayNode(Nodecurrent)
{
if(current.Left!=null)
Task.Factory.StartNew(()=>DisplayNode(current.Left),
CancellationToken.None,
TaskCreationOptions.AttachedToParent,
TaskScheduler.Default);
if(current.Right!=null)
Task.Factory.StartNew(()=>DisplayNode(current.Right),
CancellationToken.None,
TaskCreationOptions.AttachedToParent,
TaskScheduler.Default);
Console.WriteLine("当前节点的值为{0};处理的ThreadId={1}",current.Text,Thread.CurrentThread.ManagedThreadId);
}
}
}
2.3、取消任务CancellationTokenSource
usingSystem;
usingSystem.Threading;
usingSystem.Threading.Tasks;
namespaceConsoleApp1
{
classProgram
{
privatestaticintTaskMethod(stringname,intseconds,CancellationTokentoken)
{
Console.WriteLine("Task{0}isrunningonathreadid{1}.Isthreadpoolthread:{2}",
name,Thread.CurrentThread.ManagedThreadId,Thread.CurrentThread.IsThreadPoolThread);
for(inti=0;i(()=>TaskMethod("Task1",10,cts.Token),cts.Token);
Console.WriteLine(longTask.Status);
cts.Cancel();
Console.WriteLine(longTask.Status);
Console.WriteLine("Firsttaskhasbeencancelledbeforeexecution");
cts=newCancellationTokenSource();
longTask=newTask(()=>TaskMethod("Task2",10,cts.Token),cts.Token);
longTask.Start();
for(inti=0;i<5;i++)
{
Thread.Sleep(TimeSpan.FromSeconds(0.5));
Console.WriteLine(longTask.Status);
}
cts.Cancel();
for(inti=0;i<5;i++)
{
Thread.Sleep(TimeSpan.FromSeconds(0.5));
Console.WriteLine(longTask.Status);
}
Console.WriteLine("Ataskhasbeencompletedwithresult{0}.",longTask.Result);
}
}
}
2.4、处理任务中的异常
单个任务:
usingSystem;
usingSystem.Threading;
usingSystem.Threading.Tasks;
namespaceConsoleApp1
{
classProgram
{
staticintTaskMethod(stringname,intseconds)
{
Console.WriteLine("Task{0}isrunningonathreadid{1}.Isthreadpoolthread:{2}",
name,Thread.CurrentThread.ManagedThreadId,Thread.CurrentThread.IsThreadPoolThread);
Thread.Sleep(TimeSpan.FromSeconds(seconds));
thrownewException("Boom!");
return42*seconds;
}
staticvoidMain(string[]args)
{
try
{
Tasktask=Task.Run(()=>TaskMethod("Task2",2));
intresult=task.GetAwaiter().GetResult();
Console.WriteLine("Result:{0}",result);
}
catch(Exceptionex)
{
Console.WriteLine("Task2Exceptioncaught:{0}",ex.Message);
}
Console.WriteLine("----------------------------------------------");
Console.WriteLine();
}
}
}
多个任务:
usingSystem;
usingSystem.Threading;
usingSystem.Threading.Tasks;
namespaceConsoleApp1
{
classProgram
{
staticintTaskMethod(stringname,intseconds)
{
Console.WriteLine("Task{0}isrunningonathreadid{1}.Isthreadpoolthread:{2}",
name,Thread.CurrentThread.ManagedThreadId,Thread.CurrentThread.IsThreadPoolThread);
Thread.Sleep(TimeSpan.FromSeconds(seconds));
thrownewException(string.Format("Task{0}Boom!",name));
return42*seconds;
}
publicstaticvoidMain(string[]args)
{
try
{
vart1=newTask(()=>TaskMethod("Task3",3));
vart2=newTask(()=>TaskMethod("Task4",2));
varcomplexTask=Task.WhenAll(t1,t2);
varexceptionHandler=complexTask.ContinueWith(t=>
Console.WriteLine("Result:{0}",t.Result),
TaskContinuationOptions.OnlyOnFaulted
);
t1.Start();
t2.Start();
Task.WaitAll(t1,t2);
}
catch(AggregateExceptionex)
{
ex.Handle(exception=>
{
Console.WriteLine(exception.Message);
returntrue;
});
}
}
}
}
async/await的方式:
usingSystem;
usingSystem.Threading;
usingSystem.Threading.Tasks;
namespaceConsoleApp1
{
classProgram
{
staticasyncTaskThrowNotImplementedExceptionAsync()
{
thrownewNotImplementedException();
}
staticasyncTaskThrowInvalidOperationExceptionAsync()
{
thrownewInvalidOperationException();
}
staticasyncTaskNormal()
{
awaitFun();
}
staticTaskFun()
{
returnTask.Run(()=>
{
for(inti=1;i<=10;i++)
{
Console.WriteLine("i={0}",i);
Thread.Sleep(200);
}
});
}
staticasyncTaskObserveOneExceptionAsync()
{
vartask1=ThrowNotImplementedExceptionAsync();
vartask2=ThrowInvalidOperationExceptionAsync();
vartask3=Normal();
try
{
//异步的方式
TaskallTasks=Task.WhenAll(task1,task2,task3);
awaitallTasks;
//同步的方式
//Task.WaitAll(task1,task2,task3);
}
catch(NotImplementedExceptionex)
{
Console.WriteLine("task1任务报错!");
}
catch(InvalidOperationExceptionex)
{
Console.WriteLine("task2任务报错!");
}
catch(Exceptionex)
{
Console.WriteLine("任务报错!");
}
}
publicstaticvoidMain()
{
Tasktask=ObserveOneExceptionAsync();
Console.WriteLine("主线程继续运行........");
task.Wait();
}
}
}
2.5、Task.FromResult的应用
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Threading;
usingSystem.Threading.Tasks;
namespaceConsoleApp1
{
classProgram
{
staticIDictionarycache=newDictionary()
{
{"0001","A"},
{"0002","B"},
{"0003","C"},
{"0004","D"},
{"0005","E"},
{"0006","F"},
};
publicstaticvoidMain()
{
Tasktask=GetValueFromCache("0006");
Console.WriteLine("主程序继续执行。。。。");
stringresult=task.Result;
Console.WriteLine("result={0}",result);
}
privatestaticTaskGetValueFromCache(stringkey)
{
Console.WriteLine("GetValueFromCache开始执行。。。。");
stringresult=string.Empty;
//Task.Delay(5000);
Thread.Sleep(5000);
Console.WriteLine("GetValueFromCache继续执行。。。。");
if(cache.TryGetValue(key,outresult))
{
returnTask.FromResult(result);
}
returnTask.FromResult("");
}
}
}
2.6、使用IProgress实现异步编程的进程通知
IProgress
usingSystem;
usingSystem.Threading;
usingSystem.Threading.Tasks;
namespaceConsoleApp1
{
classProgram
{
staticvoidDoProcessing(IProgressprogress)
{
for(inti=0;i<=100;++i)
{
Thread.Sleep(100);
if(progress!=null)
{
progress.Report(i);
}
}
}
staticasyncTaskDisplay()
{
//当前线程
varprogress=newProgress(percent=>
{
Console.Clear();
Console.Write("{0}%",percent);
});
//线程池线程
awaitTask.Run(()=>DoProcessing(progress));
Console.WriteLine("");
Console.WriteLine("结束");
}
publicstaticvoidMain()
{
Tasktask=Display();
task.Wait();
}
}
}
2.7、Factory.FromAsync的应用(简APM模式(委托)转换为任务)(BeginXXX和EndXXX)
带回调方式的
usingSystem;
usingSystem.Threading;
usingSystem.Threading.Tasks;
namespaceConsoleApp1
{
classProgram
{
privatedelegatestringAsynchronousTask(stringthreadName);
privatestaticstringTest(stringthreadName)
{
Console.WriteLine("Starting...");
Console.WriteLine("Isthreadpoolthread:{0}",Thread.CurrentThread.IsThreadPoolThread);
Thread.Sleep(TimeSpan.FromSeconds(2));
Thread.CurrentThread.Name=threadName;
returnstring.Format("Threadname:{0}",Thread.CurrentThread.Name);
}
privatestaticvoidCallback(IAsyncResultar)
{
Console.WriteLine("Startingacallback...");
Console.WriteLine("Statepassedtoacallbak:{0}",ar.AsyncState);
Console.WriteLine("Isthreadpoolthread:{0}",Thread.CurrentThread.IsThreadPoolThread);
Console.WriteLine("Threadpoolworkerthreadid:{0}",Thread.CurrentThread.ManagedThreadId);
}
//执行的流程是先执行Test--->Callback--->task.ContinueWith
staticvoidMain(string[]args)
{
AsynchronousTaskd=Test;
Console.WriteLine("Option1");
Tasktask=Task.Factory.FromAsync(
d.BeginInvoke("AsyncTaskThread",Callback,"adelegateasynchronouscall"),d.EndInvoke);
task.ContinueWith(t=>Console.WriteLine("Callbackisfinished,nowrunningacontinuation!Result:{0}",
t.Result));
while(!task.IsCompleted)
{
Console.WriteLine(task.Status);
Thread.Sleep(TimeSpan.FromSeconds(0.5));
}
Console.WriteLine(task.Status);
}
}
}
不带回调方式的
usingSystem;
usingSystem.Threading;
usingSystem.Threading.Tasks;
namespaceConsoleApp1
{
classProgram
{
privatedelegatestringAsynchronousTask(stringthreadName);
privatestaticstringTest(stringthreadName)
{
Console.WriteLine("Starting...");
Console.WriteLine("Isthreadpoolthread:{0}",Thread.CurrentThread.IsThreadPoolThread);
Thread.Sleep(TimeSpan.FromSeconds(2));
Thread.CurrentThread.Name=threadName;
returnstring.Format("Threadname:{0}",Thread.CurrentThread.Name);
}
//执行的流程是先执行Test--->task.ContinueWith
staticvoidMain(string[]args)
{
AsynchronousTaskd=Test;
Tasktask=Task.Factory.FromAsync(
d.BeginInvoke,d.EndInvoke,"AsyncTaskThread","adelegateasynchronouscall");
task.ContinueWith(t=>Console.WriteLine("Taskiscompleted,nowrunningacontinuation!Result:{0}",
t.Result));
while(!task.IsCompleted)
{
Console.WriteLine(task.Status);
Thread.Sleep(TimeSpan.FromSeconds(0.5));
}
Console.WriteLine(task.Status);
}
}
}
//Task启动带参数和返回值的函数任务
//下面的例子test2是个带参数和返回值的函数。
privateinttest2(objecti)
{
this.Invoke(newAction(()=>
{
pictureBox1.Visible=true;
}));
System.Threading.Thread.Sleep(3000);
MessageBox.Show("hello:"+i);
this.Invoke(newAction(()=>
{
pictureBox1.Visible=false;
}));
return0;
}
//测试调用
privatevoidcall()
{
//FuncfuncOne=delegate(strings){return"fff";};
objecti=55;
vart=Task.Factory.StartNew(newFunc
以上就是深入分析C#Task的详细内容,更多关于C#Task的资料请关注毛票票其它相关文章!