C#4.0的并行库TPL,即Task(五)

C#4.0的并行库TPL,即Task(一)http://www.skcircle.com/?id=1793

C#4.0的并行库TPL,即Task(二) http://www.skcircle.com/?id=1798

C#4.0的并行库TPL,即Task(三) http://www.skcircle.com/?id=1808

C#4.0的并行库TPL,即Task(四)  http://www.skcircle.com/?id=1815

C#4.0的并行库TPL,即Task(五) http://www.skcircle.com/?id=1816



这一节再继续谈谈

Task WhenAll、WhenAny


先上代码:

代码是那本C#多线程编程书里的。

static int TaskMethod(string name, int seconds)
{
Console.WriteLine("Task {0} 运行在线程 {1} 上。是否是线程池线程: {2}",
name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
Thread.Sleep(TimeSpan.FromSeconds(seconds));
return 42 * seconds;
}


WhenAll:

这里设置了一个名字为whenAllTask的变量,他是用静态方法Task.WhenAll创建的第三个任务。需要注意的是,由于是基于前面两个任务创建的,因此返回的类型为 Task<int[]>。在firstTask和secondTask运行完毕后(WhenAll), 采用后续操作(ContinueWith),函数中的t其实也就是whenAllTask的传参。后续操作打印出whenAllTask中的Result数组成员,后续操作的状态条件为 whenAllTask的状态为OnlyOnRanToCompletion。

var firstTask = new Task<int>(() => TaskMethod("First Task", 3));
var secondTask = new Task<int>(() => TaskMethod("Second Task", 2));
var whenAllTask = Task.WhenAll(firstTask, secondTask);
whenAllTask.ContinueWith(t =>Console.WriteLine("The first answer is {0}, the second is {1}", t.Result[0], t.Result[1]),
TaskContinuationOptions.OnlyOnRanToCompletion
);
 
firstTask.Start();
secondTask.Start();


WhenAny:

首先建立一个Task List,名字为tasks。而后依次向里添加新任务实例,而且新任务的运行所需时间依次为1、2、3秒。而后,伦查tasks中的任务数量,在循环内 建立completedTask任务,用来表示任一个在tasks中已经完成操作的Task,如果一个任务都没运行完成,则completedTask。

需要指出的是, 这里的Result和上例中的不同,上例中t.Result直接指代int[],即返回结果数组;而这里的WhenAny(tasks).Result指的是Task<int>,也就是完成的Task<int>实例。


var tasks = new List<Task<int>>();
for (int i = 1; i < 4; i++)
{
int counter = i;
var task = new Task<int>(() => TaskMethod(string.Format("Task {0}", counter), counter));
tasks.Add(task);
task.Start();
}
 
while (tasks.Count > 0)
{
    var completedTask = Task.WhenAny(tasks).Result;//这里的Result是指代Task<int>!
    tasks.Remove(completedTask);
    Console.WriteLine("A task has been completed with result {0}.", completedTask.Result);
}


这里勇哥想补充的是,你可能在即时窗口中发现completedTask是有Result属性的。

但实际上completedTask.Result可能提示非法属性。


image.png

问题代码如下:

 while (TaskCount() > 0)
                    {
                        var completedTask = Task.WhenAny(TaskList).Result;
                        
                        if (completedTask.Result==-1)
                        {
                            SetIsCanceled();
                            CMessage.Instance.AddTipsMessage(CMessage.DeviceMessageTypeEnum.WorkMsg, $"Task[{completedTask.Id}]: Task被用户取消!");
                        }
                    }

其实原因是:

TaskList的定义少了返回类型。

原来是:
public readonly List<Task> TaskList = new List<Task>();
解决办法是:
public readonly List<Task<int>> TaskList = new List<Task<int>>();

这个时候你会发现completedTask.Result就可用了。
这是因为WhenAny(tasks).Result指的是Task,但是你之前的Task是不带参数的,所以没有云Result




本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2024年5月    »
12345
6789101112
13141516171819
20212223242526
2728293031
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864