第4章 使用任务并行库

  • 简介
  • 创建任务
using System;
using System.Threading.Tasks;
using static System.Console;
using static System.Threading.Thread;

namespace Chapter4.Recipe1
{
    class Program
    {
        static void Main(string[] args)
        {
            var t1 = new Task(() => TaskMethod("Task 1"));
            var t2 = new Task(() => TaskMethod("Task 2"));
            t2.Start();
            t1.Start();
            Task.Run(() => TaskMethod("Task 3"));
            Task.Factory.StartNew(() => TaskMethod("Task 4"));
            Task.Factory.StartNew(() => TaskMethod("Task 5"), TaskCreationOptions.LongRunning);
            Sleep(TimeSpan.FromSeconds(1));
        }

        static void TaskMethod(string name)
        {
            WriteLine($"Task {name} is running on a thread id " +
                      $"{CurrentThread.ManagedThreadId}. Is thread pool thread: " +
                      $"{CurrentThread.IsThreadPoolThread}");
        }
    }
}
  • 使用任务执行基本的操作
using System;
using System.Threading.Tasks;
using static System.Console;
using static System.Threading.Thread;

namespace Chapter4.Recipe2
{
    class Program
    {
        static void Main(string[] args)
        {
            TaskMethod("Main Thread Task");
            Task<int> task = CreateTask("Task 1");
            task.Start();
            int result = task.Result;
            WriteLine($"Result is: {result}");

            task = CreateTask("Task 2");
            task.RunSynchronously();
            result = task.Result;
            WriteLine($"Result is: {result}");

            task = CreateTask("Task 3");
            WriteLine(task.Status);
            task.Start();

            while (!task.IsCompleted)
            {
                WriteLine(task.Status);
                Sleep(TimeSpan.FromSeconds(0.5));
            } 
            
            WriteLine(task.Status);
            result = task.Result;
            WriteLine($"Result is: {result}");
        }

        static Task<int> CreateTask(string name)
        {
            return new Task<int>(() => TaskMethod(name));
        }

        static int TaskMethod(string name)
        {
            WriteLine($"Task {name} is running on a thread id " +
                      $"{CurrentThread.ManagedThreadId}. Is thread pool thread: " +
                      $"{CurrentThread.IsThreadPoolThread}");
            Sleep(TimeSpan.FromSeconds(2));
            return 42;
        }
    }
}
  • 组合任务
using System;
using System.Threading.Tasks;
using static System.Console;
using static System.Threading.Thread;

namespace Chapter4.Recipe3
{
    class Program
    {
        static void Main(string[] args)
        {
            var firstTask = new Task<int>(() => TaskMethod("First Task", 3));
            var secondTask = new Task<int>(() => TaskMethod("Second Task", 2));

            firstTask.ContinueWith(
                t => WriteLine(
                    $"The first answer is {t.Result}. Thread id " +
                    $"{CurrentThread.ManagedThreadId}, is thread pool thread: " +
                    $"{CurrentThread.IsThreadPoolThread}"),
                TaskContinuationOptions.OnlyOnRanToCompletion);

            firstTask.Start();
            secondTask.Start();

            Sleep(TimeSpan.FromSeconds(4));

            Task continuation = secondTask.ContinueWith(
                t => WriteLine(
                    $"The second answer is {t.Result}. Thread id " +
                    $"{CurrentThread.ManagedThreadId}, is thread pool thread: " +
                    $"{CurrentThread.IsThreadPoolThread}"),
                TaskContinuationOptions.OnlyOnRanToCompletion 
                | TaskContinuationOptions.ExecuteSynchronously);

            continuation.GetAwaiter().OnCompleted(
                () => WriteLine(
                    $"Continuation Task Completed! Thread id " +
                    $"{CurrentThread.ManagedThreadId}, is thread pool thread: " +
                    $"{CurrentThread.IsThreadPoolThread}"));

            Sleep(TimeSpan.FromSeconds(2));
            WriteLine();

            firstTask = new Task<int>(() =>
            {
                var innerTask = Task.Factory.StartNew(() => TaskMethod("Second Task", 5),
                    TaskCreationOptions.AttachedToParent);

                innerTask.ContinueWith(t => TaskMethod("Third Task", 2),
                    TaskContinuationOptions.AttachedToParent);

                return TaskMethod("First Task", 2);
            });

            firstTask.Start();

            while (!firstTask.IsCompleted)
            {
                WriteLine(firstTask.Status);
                Sleep(TimeSpan.FromSeconds(0.5));
            }
            WriteLine(firstTask.Status);

            Sleep(TimeSpan.FromSeconds(10));
        }

        static int TaskMethod(string name, int seconds)
        {
            WriteLine(
                $"Task {name} is running on a thread id " +
                $"{CurrentThread.ManagedThreadId}. Is thread pool thread: " +
                $"{CurrentThread.IsThreadPoolThread}");
            Sleep(TimeSpan.FromSeconds(seconds));
            return 42 * seconds;
        }
    }
}
  • 将APM模式转换为任务
using System;
using System.Threading.Tasks;
using static System.Console;
using static System.Threading.Thread;

namespace Chapter4.Recipe4
{
    class Program
    {
        static void Main(string[] args)
        {
            int threadId;
            AsynchronousTask d = Test;
            IncompatibleAsynchronousTask e = Test;

            WriteLine("Option 1");
            Task<string> task = Task<string>.Factory.FromAsync(
                d.BeginInvoke("AsyncTaskThread", Callback, 
                "a delegate asynchronous call"), d.EndInvoke);

            task.ContinueWith(t => WriteLine(
                $"Callback is finished, now running a continuation! Result: {t.Result}"));

            while (!task.IsCompleted)
            {
                WriteLine(task.Status);
                Sleep(TimeSpan.FromSeconds(0.5));
            }
            WriteLine(task.Status);
            Sleep(TimeSpan.FromSeconds(1));

            WriteLine("----------------------------------------------");
            WriteLine();
            WriteLine("Option 2");

            task = Task<string>.Factory.FromAsync(
                d.BeginInvoke, d.EndInvoke, "AsyncTaskThread", "a delegate asynchronous call");

            task.ContinueWith(t => WriteLine(
                $"Task is completed, now running a continuation! Result: {t.Result}"));
            while (!task.IsCompleted)
            {
                WriteLine(task.Status);
                Sleep(TimeSpan.FromSeconds(0.5));
            }
            WriteLine(task.Status);
            Sleep(TimeSpan.FromSeconds(1));

            WriteLine("----------------------------------------------");
            WriteLine();
            WriteLine("Option 3");

            IAsyncResult ar = e.BeginInvoke(out threadId, Callback, "a delegate asynchronous call");
            task = Task<string>.Factory.FromAsync(ar, _ => e.EndInvoke(out threadId, ar));

            task.ContinueWith(t => 
                WriteLine(
                    $"Task is completed, now running a continuation! " +
                    $"Result: {t.Result}, ThreadId: {threadId}"));

            while (!task.IsCompleted)
            {
                WriteLine(task.Status);
                Sleep(TimeSpan.FromSeconds(0.5));
            }
            WriteLine(task.Status);

            Sleep(TimeSpan.FromSeconds(1));
        }

        delegate string AsynchronousTask(string threadName);
        delegate string IncompatibleAsynchronousTask(out int threadId);

        static void Callback(IAsyncResult ar)
        {
            WriteLine("Starting a callback...");
            WriteLine($"State passed to a callbak: {ar.AsyncState}");
            WriteLine($"Is thread pool thread: {CurrentThread.IsThreadPoolThread}");
            WriteLine($"Thread pool worker thread id: {CurrentThread.ManagedThreadId}");
        }

        static string Test(string threadName)
        {
            WriteLine("Starting...");
            WriteLine($"Is thread pool thread: {CurrentThread.IsThreadPoolThread}");
            Sleep(TimeSpan.FromSeconds(2));
            CurrentThread.Name = threadName;
            return $"Thread name: {CurrentThread.Name}";
        }

        static string Test(out int threadId)
        {
            WriteLine("Starting...");
            WriteLine($"Is thread pool thread: {CurrentThread.IsThreadPoolThread}");
            Sleep(TimeSpan.FromSeconds(2));
            threadId = CurrentThread.ManagedThreadId;
            return $"Thread pool worker thread id was: {threadId}";
        }
    }
}
  • 将EAP模式转换为任务
using System;
using System.ComponentModel;
using System.Threading.Tasks;
using static System.Console;
using static System.Threading.Thread;

namespace Chapter4.Recipe5
{
    class Program
    {
        static void Main(string[] args)
        {
            var tcs = new TaskCompletionSource<int>();

            var worker = new BackgroundWorker();
            worker.DoWork += (sender, eventArgs) =>
            {
                eventArgs.Result = TaskMethod("Background worker", 5);
            };

            worker.RunWorkerCompleted += (sender, eventArgs) =>
            {
                if (eventArgs.Error != null)
                {
                    tcs.SetException(eventArgs.Error);
                }
                else if (eventArgs.Cancelled)
                {
                    tcs.SetCanceled();
                }
                else
                {
                    tcs.SetResult((int)eventArgs.Result);
                }
            };

            worker.RunWorkerAsync();

            int result = tcs.Task.Result;

            WriteLine($"Result is: {result}");
        }

        static int TaskMethod(string name, int seconds)
        {
            WriteLine(
                $"Task {name} is running on a thread id " +
                $"{CurrentThread.ManagedThreadId}. Is thread pool thread: " +
                $"{CurrentThread.IsThreadPoolThread}");

            Sleep(TimeSpan.FromSeconds(seconds));
            return 42 * seconds;
        }
    }
}
  • 实现取消选项
using System;
using System.Threading;
using System.Threading.Tasks;
using static System.Console;
using static System.Threading.Thread;

namespace Chapter4.Recipe6
{
    class Program
    {
        static void Main(string[] args)
        {
            var cts = new CancellationTokenSource();
            var longTask = new Task<int>(() => TaskMethod("Task 1", 10, cts.Token), cts.Token);
            WriteLine(longTask.Status);
            cts.Cancel();
            WriteLine(longTask.Status);
            WriteLine("First task has been cancelled before execution");

            cts = new CancellationTokenSource();
            longTask = new Task<int>(() => TaskMethod("Task 2", 10, cts.Token), cts.Token);
            longTask.Start();
            for (int i = 0; i < 5; i++ )
            {
                Sleep(TimeSpan.FromSeconds(0.5));
                WriteLine(longTask.Status);
            }
            cts.Cancel();
            for (int i = 0; i < 5; i++)
            {
                Sleep(TimeSpan.FromSeconds(0.5));
                WriteLine(longTask.Status);
            }

            WriteLine($"A task has been completed with result {longTask.Result}.");
        }

static int TaskMethod(string name, int seconds, CancellationToken token)
{
    WriteLine(
        $"Task {name} is running on a thread id " +
        $"{CurrentThread.ManagedThreadId}. Is thread pool thread: " +
        $"{CurrentThread.IsThreadPoolThread}");

    for (int i = 0; i < seconds; i ++)
    {
        Sleep(TimeSpan.FromSeconds(1));
        if (token.IsCancellationRequested) return -1;
    }
    return 42*seconds;
}
    }
}
  • 处理任务中的异常
using System;
using System.Threading.Tasks;
using static System.Console;
using static System.Threading.Thread;

namespace Chapter4.Recipe7
{
    class Program
    {
        static void Main(string[] args)
        {
            Task<int> task;
            try
            {
                task = Task.Run(() => TaskMethod("Task 1", 2));
                int result = task.Result;
                WriteLine($"Result: {result}");
            }
            catch (Exception ex)
            {
                WriteLine($"Exception caught: {ex}");
            }
            WriteLine("----------------------------------------------");
            WriteLine();

            try
            {
                task = Task.Run(() => TaskMethod("Task 2", 2));
                int result = task.GetAwaiter().GetResult();
                WriteLine($"Result: {result}");
            }
            catch (Exception ex)
            {
                WriteLine($"Exception caught: {ex}");
            }
            WriteLine("----------------------------------------------");
            WriteLine();

            var t1 = new Task<int>(() => TaskMethod("Task 3", 3));
            var t2 = new Task<int>(() => TaskMethod("Task 4", 2));
            var complexTask = Task.WhenAll(t1, t2);
            var exceptionHandler = complexTask.ContinueWith(t => 
                    WriteLine($"Exception caught: {t.Exception}"), 
                    TaskContinuationOptions.OnlyOnFaulted
                );
            t1.Start();
            t2.Start();

            Sleep(TimeSpan.FromSeconds(5));
        }

        static int TaskMethod(string name, int seconds)
        {
            WriteLine(
                $"Task {name} is running on a thread id " +
                $"{CurrentThread.ManagedThreadId}. Is thread pool thread: " +
                $"{CurrentThread.IsThreadPoolThread}");

            Sleep(TimeSpan.FromSeconds(seconds));
            throw new Exception("Boom!");
            return 42 * seconds;
        }
    }
}
  • 并行运行任务
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using static System.Console;
using static System.Threading.Thread;

namespace Chapter4.Recipe8
{
    class Program
    {
        static void Main(string[] args)
        {
            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 =>
                WriteLine($"The first answer is {t.Result[0]}, the second is {t.Result[1]}"),
                TaskContinuationOptions.OnlyOnRanToCompletion);

            firstTask.Start();
            secondTask.Start();

            Sleep(TimeSpan.FromSeconds(4));

            var tasks = new List<Task<int>>();
            for (int i = 1; i < 4; i++)
            {
                int counter = i;
                var task = new Task<int>(() => TaskMethod($"Task {counter}", counter));
                tasks.Add(task);
                task.Start();
            }

            while (tasks.Count > 0)
            {
                var completedTask = Task.WhenAny(tasks).Result;
                tasks.Remove(completedTask);
                WriteLine($"A task has been completed with result {completedTask.Result}.");
            }

            Sleep(TimeSpan.FromSeconds(1));
        }

        static int TaskMethod(string name, int seconds)
        {
            WriteLine(
                $"Task {name} is running on a thread id " +
                $"{CurrentThread.ManagedThreadId}. Is thread pool thread: " +
                $"{CurrentThread.IsThreadPoolThread}");

            Sleep(TimeSpan.FromSeconds(seconds));
            return 42 * seconds;
        }
    }
}
  • 使用TaskScheduler配置任务的执行

猜你喜欢

转载自www.cnblogs.com/lxwuse2008/p/10858557.html