• C#多线程实现方法——Task/Task.Factary


    Task

    使用

    Task以及Task.Factory都是在.Net 4引用的。Task跟Thread很类似,通过下面例子可以看到。

            static public void ThreadMain()
            {
                Thread t1 = new Thread(TaskWorker);
                t1.Start(3);
            }
    
            static public void TaskMain()
            {
                Task t1 = new Task(TaskWorker, 3, TaskCreationOptions.PreferFairness | TaskCreationOptions.LongRunning | TaskCreationOptions.AttachedToParent);
                Console.WriteLine(t1.Status);
                t1.Start();
                t1.Wait(); // need to wait for finishing.
            }
    
            static public void TaskWorker(object state)
            {
                int nTime = (int)state;
                for (int i = 0; i < nTime; i++)
                {
                    Thread.Sleep(100);
                    Console.WriteLine(string.Format("current thread {0} sleep for {1} miniseconds .", Task.CurrentId, (i + 1) * 100));
                }
                return;
            }

    我们看到TaskWorker都是用于Task以及Thread,都是只能接受一个参数(Action<object>),不过task可以支持工作函数具有返回值(Func<TRessult>()或者Func<object, TResult>)。但是弱的类型输入跟thread一样。Task提供返回值是为了后面说到的task结构层次有用。

    下面是调用一个具有返回值的工作函数

            static public int TaskWorkerWithReturn(object state)
            {
                int nTime = (int)state;
                for (int i = 0; i < nTime; i++)
                {
                    Thread.Sleep(100);
                    Console.WriteLine(string.Format("current thread {0} sleep for {1} miniseconds .", Task.CurrentId, (i + 1) * 100));
                }
                nTime++;
                return nTime;
            }

    主调函数为:

                Task<int> t2 = new Task<int>(TaskWorkerWithReturn, 3, TaskCreationOptions.PreferFairness | TaskCreationOptions.LongRunning | TaskCreationOptions.AttachedToParent);
                t2.Start();
                t2.Wait();
                Console.WriteLine(t2.Result);
    不管从工作函数是否有返回值,task都需要在其运行过程中至少有一个前台线程在跑,否则会直接退出,根本原因是所有task都是后台线程。task的工作函数的输入参数类型职能是object。

    同步

    对于没有返回值的工作函数需要通过内核对象来同步主调线程(例如task内置的事件,使用wait来阻塞等待);

    对于有返回值的工作函数可以通过访问其Result函数来实现阻塞等待。

            static public int TaskWorkerWithReturn(object state)
            {
                int nTime = (int)state;
                for (int i = 0; i < nTime; i++)
                {
                    Thread.Sleep(100);
                    Console.WriteLine(string.Format("current thread {0} sleep for {1} miniseconds .", Task.CurrentId, (i + 1) * 100));
                }
                nTime++;
                return nTime;
            }

    主调函数:

                Task<int> t2 = new Task<int>(TaskWorkerWithReturn, 3, TaskCreationOptions.PreferFairness | TaskCreationOptions.LongRunning | TaskCreationOptions.AttachedToParent);
                t2.Start();
                Console.WriteLine("t2:" + t2.Result);

    异步调用

    作为新的一个特性在.net 4中引入,task能实现丰富的异步调用,使用成员函数ContinueWith来响应异步工作函数的完成,注意,不一定由之前完成异步函数的线程执行

            static public void TaskMain()
            {
                Task<int> t3 = new Task<int>(FirstTask, 1);
                t3.Start();
                Task<int> t4 = t3.ContinueWith<int>(RecusiveTask);
                Task<int> t5 = t4.ContinueWith<int>(RecusiveTask);
                Task<int> t6 = t5.ContinueWith<int>(RecusiveTask).ContinueWith<int>(RecusiveTask);
                //Console.WriteLine(string.Format("final result: {0}", t6.Result));
            }
    
            static public int FirstTask(object state)
            { 
                int data = (int)state;
                for (int i = 0; i < data; i++)
                {
                    Thread.Sleep(100);
                    Console.WriteLine(string.Format("current thread {0} slept for {1} milisecond.", Task.CurrentId, (i + 1) * 100));
                }
                data++;
                return data;
            }
    
            static public int RecusiveTask(Task<int> T)
            {
                int data = T.Result;
                for (int i = 0; i < data; i++)
                {
                    Thread.Sleep(100);
                    Console.WriteLine(string.Format("current thread {0} slept for {1} milisecond.", Task.CurrentId, (i + 1) * 100));
                }
                data++;
                return data;
            }
    输出结果为:

    current thread 1 slept for 100 milisecond.
    current thread 2 slept for 100 milisecond.
    current thread 2 slept for 200 milisecond.
    current thread 3 slept for 100 milisecond.
    current thread 3 slept for 200 milisecond.
    current thread 3 slept for 300 milisecond.
    current thread 4 slept for 100 milisecond.
    current thread 4 slept for 200 milisecond.
    current thread 4 slept for 300 milisecond.
    current thread 4 slept for 400 milisecond.
    current thread 5 slept for 100 milisecond.
    current thread 5 slept for 200 milisecond.
    current thread 5 slept for 300 milisecond.
    current thread 5 slept for 400 milisecond.
    current thread 5 slept for 500 milisecond.
    final result: 6
    请按任意键继续. . .













  • 相关阅读:
    LeetCode Longest Uncommon Subsequence II
    Leetcode Longest Uncommon Subsequence I
    LeetCode 557. Reverse Words in a String III
    LeetCode 394. Decode String
    LeetCode 419. Battleships in a Board
    LeetCode 366. Find Leaves of Binary Tree
    LeetCode 408. Valid Word Abbreviation
    LeetCode 532. K-diff Pairs in an Array
    LeetCode Minimum Absolute Difference in BST
    LeetCode 414. Third Maximum Number
  • 原文地址:https://www.cnblogs.com/rogerroddick/p/2846693.html
Copyright © 2020-2023  润新知