C# 异步编程 并行编程

目录

异步编程

1. Thread 

2. Task

3. async + await

并行编程

Parallel


本篇简单记录一下异步编程和并行编程,并以下图一个 Demo 来演示,源码地址我会公布在文章结尾。

C# 异步编程 并行编程

  • 异步编程

个人觉得,异步无非就是不影响某个线程的情况下,在另外的线程里执行任务的过程。异步编程即多线程编程。C# 里多线程编程写法有很多种,这里记录三种。

  • 1. Thread 

Thread 算是比较常用的写法,出来时间也比较早,一般分带参数和不带参数两种写法:

Thread thread1 = new Thread(new ThreadStart(ThreadMethod1));//不带参数
thread1.Start();

Thread thread2 = new Thread(new ParameterizedThreadStart(ThreadMethod2));//带参数
thread2.Start(para);

某些时候,不能任由线程各自运行,比如需要等待所有线程结束后再去做某件事,这个时候就需要线程同步,同步方式有很多种,并不是本文重点,感兴趣的请自行百度。这里介绍一种事件等待方式,而这种方式就可以用到带参数的线程写法:

static void Main(string[] args)
{
	TestThread();
}

private static void TestThread()
{
	ManualResetEvent resetEvent = new ManualResetEvent(false);
	Thread thread1 = new Thread(new ParameterizedThreadStart(StartByThread));
	thread1.Start(resetEvent);
	WaitThread(resetEvent);
}

private static void StartByThread(object para)
{
	ManualResetEvent mre= (ManualResetEvent)para;
	for (int i = 1; i < 5; i++)
	{
		Console.WriteLine("Execute "+i.ToString());
		Thread.Sleep(1000);
	}
	mre.Set();
}

private static void WaitThread(ManualResetEvent e)
{
	var waits = new List<EventWaitHandle>();
	waits.Add(e);
	WaitHandle.WaitAll(waits.ToArray());
	Console.WriteLine("After Wait");
}

 C# 异步编程 并行编程

  • 2. Task

Task 是 .net 4.0 才有的,严格的说,Task 不应该放在这里和 Thread 相提并论,因为它们压根不一样,什么意思?简单的说:

  • Thread仅仅是一条线程,所有操作都是这个 Thread 完成的;
  • Task 是将多个操作封装成一个概念上原子操作,但这个操作由哪个 Thread 甚至多个 Thread 来处理并不清楚

Task 应该和 Thread pool 比较合适,因为他们是处理一类任务的。在thread pool时期,我们不能知道一个workitem是否完成,也不能在完成后知道workitem所得出的返回值,task就是封装后解决这个问题的。当然这个只是小方面。Task还优化了thread pool的调用机制,在多核的情况下可以得到更好的效率。

下面介绍 Task 写法:

Task.Factory.StartNew(() => { });//方式1

Task task = new Task(()=> { });//方式2
task.Start();

当然还有很多种重载写法,具体请自行查阅。 

同样,Task 也有等待方法 :

static void Main(string[] args)
{
	TestTask();
}

private static void TestTask()
{
	Task task1 = new Task(() => {
		Console.WriteLine("Task1 executed");
		Thread.Sleep(1000);
	});
	Task task2 = new Task(() => {
		Console.WriteLine("Task2 executed");
		Thread.Sleep(2000);
	});
	task1.Start();
	task2.Start();
	Wait(task1, task2);
}

private static void Wait(params Task[] tasks)
{
	Task.WaitAll(tasks);
	Console.WriteLine("Wait End");
}

C# 异步编程 并行编程

  • 3. async + await

async 和 await 是 .net 4.5才有的,它提供了更简洁的异步编程写法:

static void Main(string[] args)
{
	TestAync();
	Console.WriteLine("Test End");
	Thread.Sleep(2000);
}

private static async void TestAync()
{
	await Task.Run(()=> {
		Console.WriteLine("Task Run 1");
		Thread.Sleep(1000);
		Console.WriteLine("Task Run 2");
	});
}

C# 异步编程 并行编程

async 方法中,也可以等待其它 Task , 但是不能用WaitAll, 只能用WhenAll, 否则可能会卡住当前线程,比如:

static void Main(string[] args)
{
	TestAync();
	Thread.Sleep(3000);
}

private static async void TestAync()
{
	Task task1=new Task(()=> {
		Console.WriteLine("Task Run 1");
		Thread.Sleep(1000);
	});
	Task task2 = new Task(() => {
		Console.WriteLine("Task Run 2");
		Thread.Sleep(2000);
	});
	task1.Start();
	task2.Start();
	await Task.WhenAll(task1, task2);
	Console.WriteLine("After when all");
}

C# 异步编程 并行编程

  • 并行编程

异步编程中,线程之间只要互不影响,考虑同步问题即可。而在并行编程中,则要求多个线程在同一时刻同时运行。必须要有多核cpu。

  • Parallel

C#中提供了 Parallel 相关方式来支持并行编程, 举个例子:

static void Main(string[] args)
{
	Parallel.For(0, 5, (i) => {
		Console.WriteLine("Step "+i.ToString()); 
	});
}

C# 异步编程 并行编程

而我们平常用的 for 循环,则不是并行的:

static void Main(string[] args)
{
	for (int i = 0; i < 5; i++)
	{
		Console.WriteLine("Step " + i.ToString());
	}
}

C# 异步编程 并行编程

控制台程序并不能很好的展示并行与异步,这里使用一个桌面多线程示例来演示:

1.只使用异步,并没有使用并行:

C# 异步编程 并行编程

2.使用异步+并行:

C# 异步编程 并行编程

想要并行,只能使用 Thread, 使用 Task似乎达不到并行效果 。

Demo源码