您的位置:首页 > 编程语言 > C#

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

2016-12-29 00:00 381 查看
/*
线程池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());
}
}

}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: