C#多线程Task的用法

对于多线程,我们经常使用的是Thread。在我们了解Task之前,如果我们要使用多核的功能可能就会自己来开线程,然而这种线程模型在.net 4.0之后被一种称为基于“任务的编程模型”所冲击,因为task会比thread具有更小的性能开销,不过大家肯定会有疑惑,任务和线程到底有什么区别呢?

 任务和线程的区别:

1、任务是架构在线程之上的,也就是说任务最终还是要抛给线程去执行。

2、任务跟线程不是一对一的关系,比如开10个任务并不是说会开10个线程,这一点任务有点类似线程池,但是任务相比线程池有很小的开销和精确的控制

新建任务:

  class Program
    {

        static void TaskMethod()
        {
            Console.WriteLine("running in a task ");
            Console.WriteLine("Task id is {0}", Task.CurrentId);
        }
        static void Main(string[] args)
        {
            //第一种建立任务的方法,工厂创建
            var task1 = Task.Factory.StartNew(TaskMethod);

            //第二种建立任务的方法,也是工厂创建
            TaskFactory taskFactory = new TaskFactory();
            var task2 = taskFactory.StartNew(TaskMethod);

            // 第三种创建方式,直接实例化
            var task3 = new Task(TaskMethod);
            task3.Start();
            Console.ReadKey();
        }
    }

通过使用任务,可以指定某个任务完成后,应开始运行另一个任务。

等待任务Wait();WaitAll(),Task.ContinueWith

 static void Main(string[] args)
        {
            var task1 = new Task(() =>
            {
                Console.WriteLine("Begin");
                System.Threading.Thread.Sleep(3000);
                Console.WriteLine("Finish");
            });
            Console.WriteLine("Before start:" + task1.Status);
            task1.Start();
            Console.WriteLine("After start:" + task1.Status);
            task1.Wait();
            Console.WriteLine("After Finish:" + task1.Status);

            Console.ReadKey();
        }
 static void Main(string[] args)
        {
            var task1 = new Task(() =>
            {
                Console.WriteLine("Task 1 Begin");
                System.Threading.Thread.Sleep(2000);
                Console.WriteLine("Task 1 Finish");
            });

            var task2 = new Task(() =>
            {
                Console.WriteLine("Task 2 Begin");
                System.Threading.Thread.Sleep(3000);
                Console.WriteLine("Task 2 Finish");
            });

            task1.Start();
            task2.Start();
            Task.WaitAll(task1, task2);
            Console.WriteLine("All task finished!");

            Console.ReadKey();
        }

就是在第一个Task完成后自动启动下一个Task,实现Task的延续,下面我们来看下它的用法,编写如下代码

 static void Task2Method(Task test)
        {
            Console.WriteLine("running in a task{0} ",test.Id);
            Console.WriteLine("Task id is {0}", Task.CurrentId);
            System.Threading.Thread.Sleep(3000);
            Console.WriteLine("Task {0} Finish ", test.Id);
        }
        static void Main(string[] args)
        {
            var task1 = new Task(() =>
            {
                Console.WriteLine("Task 1 Begin task{0} ", Task.CurrentId);
                System.Threading.Thread.Sleep(3000);
                Console.WriteLine("Task 1 Finish");
            });
            
            task1.Start();

            Task task2 = task1.ContinueWith(Task2Method);

            Console.ReadKey();
        }

 

或者

 static void Main(string[] args)
        {
            var SendFeedBackTask = Task.Factory.StartNew(() => { Console.WriteLine("Get some Data!"); })
                             .ContinueWith<bool>(s => { return true; })
                             .ContinueWith<string>(r =>
                             {
                                 if (r.Result)
                                 {
                                     return "Finished";
                                 }
                                 else
                                 {
                                     return "Error";
                                 }
                             });
            Console.WriteLine(SendFeedBackTask.Result);
            Console.Read();
        }

首先输出Get some data,然后执行第二个获得返回值true,最后根据判断返回Finished或error。输出结果:

Get some Data!

Finished

其实上面的写法简化一下,可以这样写:

Task.Factory.StartNew<string>(() => {return "One";}).ContinueWith(ss => { Console.WriteLine(ss.Result);});

 

取消任务

如何取消一个Task呢,我们通过cancellation的tokens来取消一个Task。在很多Task的Body里面包含循环,我们可以在轮询的时候判断IsCancellationRequested属性是否为True,如果是True的话就return或者抛出异常

 

var tokenSource = new CancellationTokenSource();
            var token = tokenSource.Token;
            var task = Task.Factory.StartNew(() =>
            {
                Console.WriteLine("Task id is {0}", Task.CurrentId);
                for (var i = 0; i < 1000; i++)
                {
                    Console.WriteLine("Task is running ,i is {0}", i);
                    System.Threading.Thread.Sleep(1000);
                    if (token.IsCancellationRequested)
                    {
                        Console.WriteLine("Abort mission success!");
                        return;
                    }
                }
            }, token);
            token.Register(() =>
            {
                Console.WriteLine("Canceled");
            });
            Console.WriteLine("Press enter to cancel task...");
            Console.ReadKey();
            tokenSource.Cancel();
            Console.ReadKey();

这里开启了一个Task,并给token注册了一个方法,输出一条信息,然后执行ReadKey开始等待用户输入,用户点击回车后,执行tokenSource.Cancel方法,取消任务.

 

参考:

https://www.cnblogs.com/yunfeifei/p/4106318.html

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值