1,Task对象都有一组字段,这些字段构成了任务的状态:
id----任务的唯一标识
可以使用 Task.CurrentId 静态属性来查询 当前正在调试的代码的ID.
Status:
Created:任务显示创建
WaitingForActivation:任务通过ContinueWith函数创建.会自动开始
WaitingToRan,任务正在调度,但是未执行
Running,任务正在执行
WaitingForChildrenToComplete:正在等待其子进程完成后才能完成.
(设置TaskCreationOption.AttachedToParent)
最终是以下三个状态之一
RanToCompletion
Canceled
Faulted
2,TaskFactory
public static void TaskFactory() { Task parent = new Task(() => { var cts = new CancellationTokenSource(); var tf = new TaskFactory<Int32>(cts.Token, TaskCreationOptions.AttachedToParent, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default); // This tasks creates and starts 3 child tasks var childTasks = new[] { tf.StartNew(() => Sum(cts.Token, 10000)), tf.StartNew(() => Sum(cts.Token, 20000)), tf.StartNew(() => Sum(cts.Token, Int32.MaxValue)) // Too big, throws OverflowException }; // If any of the child tasks throw, cancel the rest of them for (Int32 task = 0; task < childTasks.Length; task++) childTasks[task].ContinueWith(t => cts.Cancel(), TaskContinuationOptions.OnlyOnFaulted); // When all children are done, get the maximum value returned from the non-faulting/canceled tasks // Then pass the maximum value to another task which displays the maximum result tf.ContinueWhenAll(childTasks, completedTasks => completedTasks.Where(t => !t.IsFaulted && !t.IsCanceled).Max(t => t.Result), CancellationToken.None) .ContinueWith(t => Console.WriteLine("The maximum is: " + t.Result), TaskContinuationOptions.ExecuteSynchronously).Wait(); // Wait is for testing only }); // When the children are done, show any unhandled exceptions too parent.ContinueWith(p => { // I put all this text in a StringBuilder and call Console.WrteLine just once because this task // could execute concurrently with the task above & I don't want the tasks' output interspersed StringBuilder sb = new StringBuilder("The following exception(s) occurred:" + Environment.NewLine); foreach (var e in p.Exception.Flatten().InnerExceptions) sb.AppendLine(" " + e.GetType().ToString()); Console.WriteLine(sb.ToString()); }, TaskContinuationOptions.OnlyOnFaulted); // Start the parent Task so it can start its children parent.Start(); }
1,创建了一个任务工程,所有的子任务都是以相同方式配置.startNew 或者continuewith 的任务.都视为 TaskFactory的子任务.
注意,TaskFactory返回一个任务数组.
2,配置中,表示所有的子任务的父任务都是parent,包括continueWhenAll之类的.
3,当调用cts.cancel()的时候,注意,为了不让后面的几个continueWhenAll函数取消调用 的 ConcellationToken.None来保证该
Continue不被取消(因为在TaskFactory里面设置了取消,如果默认的话,这个Continue会被取消掉).
4,AttachParent 和 ExecuteSynchronously()的区别.
前者一般实在线程创建的时候,表示父线程必须要等待子线程全部完成后才算完成.
后者表达了该线程的延续任务(ContinueWith)任务,在本来任务的线程上执行就是在同一个线程上面执行.
上面表达的意思是,子任务的后续任务跟子任务使用同一个线程.
3,任务调度器
TaskScheduler.Default:使用线程池
TaskScheduler.FromCurrentSynchronizationContext 获得一个同步的上下文调度器的使用,可以用来在Form程序中方便的
在异步线程中更新UI界面.否则需要使用Invoke的方式:
4,微软实列代码地址https://docs.microsoft.com/zh-cn/samples/browse/?redirectedfrom=MSDN-samples
5,https://docs.microsoft.com/en-us/previous-versions/msp-n-p/ff963552(v=pandp.10)
使用Parallel.For进行循环任务
Parallel.ForEach 来进行迭代任务
Parallel.Invoke进行多个方法执行.
Parallel方法都接受一个ParallelOption参数:
public class ParallelOptions { public ParallelOptions() { } public CancellationToken CancellationToken { get; set; } public Int32 MaxDegreeOfParallelism { get; set; }//最大线程数,默认=-1,为cpu的数量 public TaskScheduler TaskScheduler { get; set; } }
另外其还支持3个委托函数协助处理
public static Int64 DirectoryBytes(string path, string searchPattern, SearchOption searchOption) { var files = Directory.EnumerateFiles(path, searchPattern, searchOption);//枚举所有的文件. Int64 mastertotals = 0;//累计全部bytes ParallelLoopResult result = Parallel.ForEach<String, Int64>( files,//tsource---需要处理的迭代对象. () =>0,//Tlocal---每个初始化值,传递给body. (file, loopState, taskLocalTotal) =>//处理函数,file是tsource的一个,loopstate是循环控制对象,taskLocakTotal是第一个 //函数传递下来TLocal的初始值.用于给body使用. { Int64 fileLength = 0; FileStream fs = null; try { fs = File.OpenRead(file); fileLength = fs.Length; } catch (IOException) { } finally { if (fs != null) fs.Dispose(); } return taskLocalTotal + fileLength; }, taskLocalTotal =>//这个参数是body函数的返回值,传递给Finally函数.Initial->Body->Finally. { Interlocked.Add(ref mastertotals, taskLocalTotal);//安全的进行数据操作. } ); return mastertotals;//返回值. }
1,该函数的原型:
ParallelLoopResult ForEach<TSource,TLocal> (
IEnumerable<TSource> source, Func<TLocal> localInit,
Func<TSource,System.Threading.Tasks.ParallelLoopState,long,TLocal,TLocal> body,
Action<TLocal> localFinally);
2,ParallelLoopResult
IsCompleted
获取该循环是否已运行完成(即,该循环的所有迭代均已执行,并且该循环没有收到提前结束的请求)。
LowestBreakIteration
获取从中调用 Break() 的最低迭代的索引。
3,三个委托之间的关系:
Func<TLocal>:用于初始化一个本地对象.
Func<TSource,System.Threading.Tasks.ParallelLoopState,long,TLocal,TLocal> body,
用于处理对象,
Tsource:处理源
ParallelLoopState:状态控制字
属性:IsExceptional:是否发生异常
IsStopped : 是否调用Stop方法//会触发ShouldExit
LowestBreakIteration:最低调用break的迭代
ShouldExitCurrentIteration:
在调用了break,stop或者异常,或者ParallelOption中的CancellationToken也会为true
stop();立即停止处理项
break();在处理完当前项后,尽快停止处理项.(保证处理完当前项)但是不保证该项是最后处理的项.所以,LowestBreakIteration保存了最低处理的项.
4,可通过检查结果来了解:
如果complete=true ,则表明完成
如果LowestBreakIteration!=null则表明在某项调用了break
=null,则表明调用了stop方法.如果抛出异常,应该捕捉AggregateException来得体的恢复.