C# 多线程、异步线程、线程池相关知识

/*
线程池ThreadPool类会在需要时增减池中线程的线程数,直到最大的线程数。池中的最大线程数是可配置的。
在双核CPU中,默认设置为1023个工作线程和1000个I/O线程。也可以指定在创建线程池时应立即启动的最小线程数,
以及线程池,中可用的最大线程数。如果有更多的作业要处理,线程池中线程的个数也到了极限,
最新的作业就要排队,且必须等待线程完成其任务。
*/

//下面这个方法是一个符合WaitCallBack委托的方法:
static void WaitCallBackMethod(object param)
{
     for (int i = 0; i < 5; i++)
     {
         Console.WriteLine(String.Format("Thread {0} is running", param));
         Thread.Sleep(1000);
     }
}
//然后在主线程里给线程池添加方法,QueueUserWorkItem()方法的第二个参数是个object类型的参数,可传入一个数据到线程中

static void Main(string[] args)
{
     for (int i = 1; i <= 3; i++)
     {
         ThreadPool.QueueUserWorkItem(WaitCallBackMethod, i);
     }
     Console.Read();
}

/////////////////////////////////////////////////////////////////
//Task任务
1、Task类构造函数

使用Task类的构造函数。实例化Task对象时,任务不会立即运行,而是指定Created状态。
接着调用Task类的Start()方法来启动任务。
使用Task类时,除了调用Start()方法,还可以调用RunSynchronously()方法。
这样,任务也会启动,但是同时调用。默认情况下,任务是异步运行的。
Task类的构造函数接收一个无参无返回值的委托:

Task task = new Task(TaskMethod);
task.Start();

下面是TaskMethod方法:
static void TaskMethod()
{
    for (int i = 0; i < 10; i++)
    {
        Console.WriteLine(String.Format("Running in a task. Task ID: {0}", Task.CurrentId));
        Thread.Sleep(500);
    }
}

方法里用Task.CurrentId属性取得当前任务ID。下面是主线程:
static void Main(string[] args)
{
    Task task = new Task(TaskMethod);
    task.Start();
 
    for (int i = 0; i < 10; i++)
    {
        Console.WriteLine("Running in main thread.");
        Thread.Sleep(500);
     }
     
     Console.Read();
}

如果要往线程里传递参数,Task构造函数提供的重载,可以传入一个object类型的参数:
Task task = new Task(TaskMethodWithParameter, "Hello world");
task.Start();

下面是带参的线程方法:
static void TaskMethodWithParameter(object param)
{
    for (int i = 0; i < 10; i++)
    {
        Console.WriteLine(String.Format("Running in a task. Parameter: {0}", param));
        Thread.Sleep(500);
    }
}

2、TaskFactory类
使用实例化的TaskFactory类,在其中把TaskMethod方法传递给StartNew()方法,就会立即启动任务。
TaskFactory tf = new TaskFactory();
tf.StartNew(TaskMethod);

3、Task.Factory属性
Task类提供了一个Factory静态属性,这个属性返回一个TaskFactory对象。
Task task = Task.Factory.StartNew(TaskMethod);


///////////////////////////////////////////////////////////////////////////////////
C#异步编程的实现方式——连续任务

通过任务,可以指定在任务完成后,应开始运行另一个特定任务。任务处理程序或者不带参数或者带一个对象参数,而连续处理程序有一个Task类型的参数。下面先定义两个任务:

static void FirstTaskMethod()
{
    Console.WriteLine(String.Format("Task {0} is doing something", Task.CurrentId));
    Thread.Sleep(200);
}
 
static void SecondTaskMethod(Task task)
{
    Console.WriteLine("Last task is finished");
    Console.WriteLine(String.Format("Task {0} is doing something", Task.CurrentId));
    Thread.Sleep(200);
}

连续任务通过在任务上调用ContinueWith()方法来现实:
static void Main(string[] args)
{
    Task task1 = new Task(FirstTaskMethod);
    Task task2 = task1.ContinueWith(SecondTaskMethod);
    task1.Start();
 
    for (int i = 0; i < 20; i++)
    {
        Console.WriteLine("Main thread is running");
        Thread.Sleep(200);
    }
 
    Console.Read();
}
主线程循环输出字符串到控制台,Task1任务在另外一个线程里运行,FirstTaskMethod执行完继续SecondTaskMethod
值得注意的是,在一个任务结束时,可以启动多个任务,也就是说,任务的连接可以像一个树结构那样,如下代码:

Task task1 = new Task(FirstTaskMethod);
Task task2 = task1.ContinueWith(SecondTaskMethod);
Task task3 = task1.ContinueWith(SecondTaskMethod);
Task task4 = task2.ContinueWith(SecondTaskMethod);
Task task5 = task2.ContinueWith(SecondTaskMethod);
无论前一个任务是如何结束的,后面的连续任务总是在前一个任务结束时启动。
TaskContinuationOptions枚举提供了OnlyOnFaulted,NotOnFaulted,OnlyOnCanceled,
NotOnCanceled,OnlyOnRunToCompletion几个选项。我们可以指定只有当前一个任务成功结束时才启动:

Task task5 = task2.ContinueWith(SecondTaskMethod, TaskContinuationOptions.OnlyOnRanToCompletion);


///////////////////////////////////////////////////////////////////////////////////
C#异步编程的实现方式——层次任务

任务也可以构成一个层次结构。一个任务启动一个新任务时,就启动了一个层次结构。
下面的代码段在父任务内部新建一个任务。创建子任务的代码与创建父任务的代码相同,
唯一的区别是这个任务从另一个任务内部创建:

static void Main(string[] args)
{
    Task parentTask = new Task(ParentTask);
    parentTask.Start();
 
    Console.Read();
}
 
static void ParentTask()
{
    Console.WriteLine("Parent task is starting");
	Task childTask= new Task(ChildTask,TaskCreationOptions.AttachedToParent);
    childTask.Start();
    Thread.Sleep(2000);
    Console.WriteLine("Parent task is finished");
}
 
static void ChildTask()
{
    Console.WriteLine("Child task started");
    Thread.Sleep(4000);
    Console.WriteLine("Child task is finished");
}


///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////

using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace Ex.RulesTester.Threads
{
    /// <summary>
    /// Task异步等待所有线程结束通知测试
    /// </summary>
    [TestClass]
    public class TaskAllCompleteTester
    {
        [TestMethod]
        public void TestTaskPoolStatus()
        {
            //运行异步多任务
            TaskTest.RunTask();
            var list = TaskTest.SuccessList;
            bool isAllComplete = false;
            //等待异步通知
            while (!isAllComplete)
            {
                isAllComplete = TaskTest.IsAllComplete;
                list = TaskTest.SuccessList;
            }

            Assert.IsTrue(true);
        }
        /// <summary>
        /// 对于 task 多任务执行的封装
        /// </summary>
        private class TaskTest
        {
            private static object m_lock = new object();
            public static List<string> SuccessList = new List<string>();
            private static string msg = "";
            public static bool IsFinish = false;
            public static List<Task> TaskList = new List<Task>();
            static bool isAllComplete = false;
            /// <summary>
            /// 标记所有任务是否全部执行完毕
            /// </summary>
            public static bool IsAllComplete
            {
                get { return isAllComplete; }
            }

            private TaskTest()
            {

            }

            public static void RunTask()
            {
                //运行5个任务
                for (int i = 1; i <= 5; i++)
                {
                    var task = Task.Factory.StartNew(DoTask, i);
                    TaskList.Add(task);
                }
                //异步等待所有任务执行完毕
                Task.Factory.StartNew(x =>
                {
                    Task.WaitAll(TaskList.ToArray());
                    //标记所有任务运行完成
                    isAllComplete = true;
                }, null);
            }
            private static void DoTask(object par)
            {
                Thread.Sleep(int.Parse(par.ToString()) * 1000);
                lock (m_lock)
                {
                    SuccessList.Add("Has Completed T" + par.ToString());
                }
            }

        }
    }
}

原文地址:https://www.cnblogs.com/smartsmile/p/6234066.html