欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C#多线程Task的用法

程序员文章站 2022-05-05 18:00:01
...

对于多线程,我们经常使用的是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方法,取消任务.

C#多线程Task的用法

 

参考:

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

相关标签: C#