c#中任务:Task、TaskFactory简单使用方法

上下文可以很好的在线程之间传递值

 

CallContext.LogicalSetData("Name", "Jackey");
string s = (string)CallContext.LogicalGetData("Name");
也可以用 ExecutionContext.SuppressFlow(); 来阻止上下文的流动

 

Task在并行计算中的作用很凸显,首次构造一个Task对象时,他的状态是Created。以后,当任务启动时,他的状态变成WaitingToRun。Task在一个线程上运行时,他的状态变成Running。任务停止运行,并等待他的任何子任务时,状态变成WaitingForChildrenToComplete。任务完全结束时,它进入以下三个状态之一:RanToCompletion,Canceled或者Faulted。一个Task<TResult>运行完成时,可通过Task<TResult>的Result属性来查询任务的结果,一个Task或者Task<TResult>出错时,可以查询Task的Exception属性来获得任务抛出的未处理的异常,该属性总是返回一个AggregateException对象,他包含所有未处理的异常。
为简化代码,Task提供了几个只读的Boolean属性,IsCanceled,IsFaulted,IsCompleted。注意,当Task处于RanToCompleted,Canceled或者Faulted状态时,IsCompleted返回True。为了判断一个Task是否成功完成,最简单的方法是
if(task.Status == TaskStatus.RanToCompletion)。

 

普通的Task调用 ,如果你想要有返回的结果,要使用Task<>

 

static void Main(string[] args)
{
Task<double> task = new Task<double>( o => Sum((double)o),5000.0);
task.Start();
task.Wait();
Console.WriteLine(task.Result);

 

Console.Read();
}

 

public static double Sum(double CountdownEvent)
{
double sum = 0;
for (double i = 0; i < CountdownEvent; i++)
{
sum += i;
}
return sum;
}
}

 

一个任务结束后启动另一个

 

static void Main(string[] args)
{
Task<double> one = new Task<double>(o => Sum((double)o), 5000.0);
one.Start();
Task two = one.ContinueWith(task => Console.WriteLine("The result is: {0}", one.Result));

 

Console.Read();
}

 

 

 

有父任务来来带动所有子任务

 

static void Main(string[] args)
{
Task<double[]> parent = new Task<double[]>(
() =>
{
var result = new double[3]; //create a array to save result
// parallel 3 child tasks
new Task(() => result[0] = Sum(10000.0), TaskCreationOptions.AttachedToParent).Start();
new Task(() => result[1] = Sum(20000.0), TaskCreationOptions.AttachedToParent).Start();
new Task(() => result[2] = Sum(30000.0), TaskCreationOptions.AttachedToParent).Start();

 

// return result
return result;
});
var cwt = parent.ContinueWith(parentTask => Array.ForEach(parentTask.Result, Console.WriteLine));
parent.Start();

Console.Read();
}

 

TaskFactory也是很有用的类,但是稍微复杂了一点,当一组Task对象来共享相同的状态时,可以使用这个类型

 

static void Main(string[] args)
{
// create task factory
Task parent = new Task(
() =>
{
var cts = new CancellationTokenSource();
var tf = new TaskFactory<double>(cts.Token,
TaskCreationOptions.AttachedToParent,
TaskContinuationOptions.ExecuteSynchronously,
TaskScheduler.Default);

 

// create paraller 3 tasks
var childTasks = new[] {
tf.StartNew( ()=> Sum(cts.Token,10000.0)),
tf.StartNew( ()=> Sum(cts.Token,20000.0)),
tf.StartNew(()=> Sum(cts.Token, Int32.MaxValue))};

 

// any child task throw exception, cancel all the child task
for (int i = 0; i < childTasks.Length; i++)
childTasks[i].ContinueWith(t => cts.Cancel(), TaskContinuationOptions.OnlyOnFaulted);

 

// after all tasks finish, get max from where were successfully, return the max
tf.ContinueWhenAll(
childTasks,
completeTask => completeTask.Where(
t => !t.IsFaulted && !t.IsCanceled).Max(t => t.Result),
CancellationToken.None)
.ContinueWith(t => Console.WriteLine("The Maximun is: {0}", t.Result),
TaskContinuationOptions.ExecuteSynchronously);
});

 

// show all the exceptions
parent.ContinueWith( p=>{
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);

 

parent.Start();
parent.Wait();
Console.WriteLine("OK");
Console.Read();
}

 

public static double Sum(CancellationToken token, double CountdownEvent)
{
double sum = 0;
for (double i = 0; i < CountdownEvent; i++)
{
token.ThrowIfCancellationRequested(); //if source.cancel, this will throw OperationCanceledException
sum += i;
}
return sum;
}

 

这里我发现一个问题,我想测试 TaskContinuationOpstions枚举功能的时候总是有问题

 

task.ContinueWith(o =>
{ Console.WriteLine("Get Cancel..."); }, TaskContinuationOptions.OnlyOnCanceled);

 

怎么都不起作用,但是其他的选项倒是可以,索性

 

task.ContinueWith(o =>
{ if (cts.IsCancellationRequested) Console.WriteLine("Get Cancel..."); });

 

自己去判断一下是否是终止来实现。Method prototypes is below:

 

public static double Sum(CancellationToken token, double CountdownEvent)
{
while (true)
{
if (token.IsCancellationRequested)
return default(double);
Console.WriteLine(DateTime.Now.ToLongTimeString());
Thread.Sleep(1000);
}
return (double)DateTime.Now.Millisecond;
}

 

task.ContinueWith(o =>
{ if (cts.IsCancellationRequested) Console.WriteLine("Get Cancel..."); });



评论: 1 | 引用: 0 | 查看次数: -
3333[2019-08-14 05:44 PM | | | 111.194.60.112 | del | 通过审核 | 回复回复]
沙发
[正在加载评论信息,请稍候...]
发表评论
昵 称:
密 码: 游客发言不需要密码.
邮 箱: 邮件地址支持Gravatar头像,邮箱地址不会公开.
网 址: 输入网址便于回访.
内 容:
验证码:
选 项:
虽然发表评论不用注册,但是为了保护您的发言权,建议您注册帐号.
字数限制 1000 字 | UBB代码 开启 | [img]标签 关闭