C# 并发编程之一

1、常见术语

  • 并发:一次不止完成一件事。

只要让应用程序同时执行多项任务,就要用到并发。

注意:

        在现代应用程序中,直接使用低层级的线程类型几乎毫无价值,但与传统的多线程相比,高层级抽象更为强大、高效。

        因此,对应已然过时的技术,本系列的多线程方法均不会赘述也不使用Thread类型或BackgroundWorker类型,它们已经有了更高高级的代替方案。

  • 多线程:采用多个执行线程的并发形式。

多线程是一种并发形式,但并发唯一的形式。

  • 并行处理:将大量的工作划分到多个并发运行的线程里,从而处理这些工作。

并行处理/并行编程,通过多线程最大化地利用多个处理器核心(每个线程都由格子的核心运行)。并行处理/编程是一种多线程形式,而多线程是一种并发形式。

  • 异步编程:一种通过future或回调来规避多余线程的并发形式。

        future(或promise)是一种类型,代表了某种会在将来完成的操作。

        .NET中的future类型有Task和Task。比较老的异步API使用的是回调或者事件,而非future。

        异步编程的核心思想是异步操作,也就是说,某个操作已经开始,但一段时间后才会去完成。虽然该操作已经在执行中,但它并不会阻塞原来的线程,而且启动该操作的线程依旧可以自由地进行其他工作。当该操作完成时,它便告知相关future,或者调用其回调或者事件,让应用程序知晓该操作已经完成了。

        异步编程是一种强大的并发形式,需要几位复杂的代码。

        但是async和await使得异步编程几乎变得和同步一样简单。 

  • 响应式编程:一种声明式编程,其中应用程序会对事件做出响应。

响应式编程是另一种并发形式,它是基于异步事件,而非异步操作。 

        异步事件不见得有一个正在意义上的”开始“,它可能会在任何事件发生,可能多次发生,比如用户的输入。

响应式编程并不一定是并发的,但它与并发密切相关。

2、异步编程

  • async 

在声明方法时,添加async关键字。它会发挥两重用途:

激活该方法种的await关键字,并知会编译器为该方法生成一个状态机,类似于yield return的工作方式。如果aysnc方法有返回值,那么这个之可能是Task。如果没有返回值,那么就返回Task。

此外,若async方法以一组枚举返回多个值,它便会返回IAsyncEnumberable或IAsyncEnumberator。这些类似于task的类型都代表future,这些future则会的async方法完成时通知调用调用代码。

注意:

        只要在编写async事件处理程序时,才需要使用async方法来返回void。

        无返回值的常规async方法都应当返回Task,而非void。

  • await

await关键字并不仅限于处理任务,它也可以处理任何特定格式的可等待对象

        例如:ValueTask类型,如果结果时同步的(比如能从内存缓存种读取),那么这种类型可以减少内存占用。ValueTask并不能直接转换成Task,但由于它遵循可等待模式,因此可以直接对他使用await。

但在大多数情况下,await处理的时Task或Task

两种方法来创建Task实例。

(1)某些任务代表的是CPU需要执行的实际代码,这些需要调用Task.Run来创建这些运算的任务。但如果要做某个特定的调度器上运行这些任务,那么需要调用Task.Factory.StartNew。

(2)另一些任务代表的是通知,创建这种基于事件的任务应当采用TaskCompletionSource(或者它的某种快捷方式)。大多数I/O任务采用了TaskCompletionSource

3、并行编程

并行编程可以提交客户端系统的CPU利用率。

但对服务器端系统而言,这通常并不适用。大多数服务器拥有并行机制,比如,ASP.NET就会并行处理多个请求。

但在某些情况下(假如一直并发用户的数量始终较低),在服务器上编写并行代码可能仍旧有用。但总体来看,服务器上的并行编程会与其内置的并行机制冲突,因而不会代理任何实际的益处。

并行机制分为数据并行和任务并行。

数据并行:当有一堆数据项需要处理,而且每一份

你可能感兴趣的:(c#,并发,并发编程)