C#基于任务的异步模式

using System;
using System.Threading;
using System.Threading.Tasks;
using static System.Console;

//异步编程
//1.异步模式 
//2.基于事件的异步模式
//3.基于任务的异步模式


namespace ConsoleApp
{
    class Program
    {
        public static void TaskMethod(object o)
        {
            Log(o?.ToString());
        }

        private static object s_logLock = new object();

        public static void Log(string title)
        {
            lock (s_logLock)
            {
                WriteLine(title);
                WriteLine($"TaskID:{Task.CurrentId?.ToString() ?? "no task"}, " +
                    $"thread:{Thread.CurrentThread.ManagedThreadId}");
                WriteLine($"is background thread: {Thread.CurrentThread.IsBackground}");
                WriteLine();
            }
        }


        static void Main(string[] args)
        {
            //StartNew和Run会立即启动
            //方法1
            var tf = new TaskFactory();
            Task t1 = tf.StartNew(TaskMethod, "using a task factory");

            //方法2
            Task t2 = Task.Factory.StartNew(TaskMethod, "factory via task");

            //方法3
            var t3 = new Task(TaskMethod, "using a task constructor and Start");
            t3.Start();

            //方法4
            Task t4 = Task.Run(() => TaskMethod("using the Run method"));


            t1.Wait();
            t2.Wait();
            t3.Wait();
            t4.Wait();

            //主线程没有任务ID,也不是线程池中的线程
            TaskMethod("main thread");
            var t5 = new Task(TaskMethod, "run sync");
            //会使用相同的线程作为主调线程
            t5.RunSynchronously();


            //如果任务的代码长时间运行,就应该使用TaskCreationOptions.LongRunning
            //即告诉任务调度器创建一个新的线程,而不使用线程池中的线程
            var t6 = new Task(TaskMethod, "long running",
                TaskCreationOptions.LongRunning);
            t6.Start();

            //任务结果 future
            //使用泛型Task<TResult>
            var t7 = new Task<Tuple<int, int>>(TaskWithResult, Tuple.Create(8, 3));
            t7.Start();
            WriteLine(t7.Result);
            t7.Wait();
            WriteLine($"result from task: {t7.Result.Item1} {t7.Result.Item2}");


            //连续的任务
            //一个要使用前一个任务的结果,如果前一个失败了,这个任务就应该执行一些清理工作
            //无论前一个任务是如何结束的,后面的任务都会接着启动
            Task t8 = new Task(DoOnFirst);
            Task t9 = t8.ContinueWith(DoOnSecond);
            Task t10 = t8.ContinueWith(DoOnSecond);
            Task t11 = t9.ContinueWith(DoOnSecond);
            t8.Start();
            //出错时启动
            Task t12 = t8.ContinueWith(DoOnSecond, TaskContinuationOptions.OnlyOnFaulted);

            Task.WaitAll(t8, t9, t10, t11);

            //任务取消
            CancelTask();

            ReadKey();
        }

        public static Tuple<int, int> TaskWithResult(object divsion)
        {
            if (divsion is Tuple<int, int>)
            {
                Tuple<int, int> div = (Tuple<int, int>)divsion;
                int result = div.Item1 / div.Item2;
                int reminder = div.Item1 % div.Item2;
                WriteLine("task creates a result...");
                return Tuple.Create(result, reminder);
            }
            return null;
        }

        private static void DoOnFirst()
        {
            WriteLine($"doing some task {Task.CurrentId}");
            Task.Delay(1000).Wait();
        }

        private static void DoOnSecond(Task t)
        {
            WriteLine($"task {t.Id} finished");
            WriteLine($"this task id {Task.CurrentId}");
            WriteLine("do some cleanup");
            Task.Delay(1000).Wait();
        }

        public static void CancelTask()
        {
            var cts = new CancellationTokenSource();
            //注册一个将在取消此CancellationToken时调用的委托。
            cts.Token.Register(() => WriteLine("*** task canceled"));
            //在指定的毫秒数后计划对此CancellationTokenSource 的取消操作。
            cts.CancelAfter(500);
            //cts.Cancel();//立即取消

            Task t1 = Task.Run(() =>
           {
               WriteLine("in task");
               while (true)
               {
                   Task.Delay(100).Wait();
                   CancellationToken token = cts.Token;
                   if (token.IsCancellationRequested)
                   {
                       WriteLine("canceling was requested, " +
                           "canceling from within the task");
                       token.ThrowIfCancellationRequested();
                       break;
                   }
                   WriteLine("in loop");
                   Task.Yield();
               }
               WriteLine("task finished without cancellation");

           }, cts.Token);

            try
            {
                t1.Wait();
            }
            catch(AggregateException ex)
            {
                WriteLine($"exception: {ex.GetType().Name}, {ex.Message}");
                foreach(var innerException in ex.InnerExceptions)
                {
                    WriteLine($"inner exception: {ex.InnerException.GetType()}," +
                        $"{ex.InnerException.Message}");
                }
            }

        }
    }
}

 

posted @ 2018-09-06 17:23  xslwm  阅读(814)  评论(0编辑  收藏  举报