什么.NET 4.5(或更早)更高级别的结构使线程更容易?(What .NET 4.5 (or ea

2019-07-29 08:33发布

代表们有一些,使在.NET线程更容易的对象的引用 。 它们可用于异步调用的方法。 在框架4.5(或更早),使线程的使用更容易或更不容易出错的有哪些其他的对象?

什么是其他抽象使并发和多线程更容易?

注意:这个问题将更新此 。

Answer 1:

我倾向于回答很多关于多线程的问题,我经常看到各种不同的方式问同样的基本问题。 我将介绍最常见的问题,因为我看到他们多年来和解释新技术如何做出更容易解决这些问题。

关闭了循环变量

这是不特定线程的问题,而是使用线程的绝对放大的问题。 C#5.0修复了这个问题的foreach通过创建每个迭代一个新的可变环。 您将不再需要创建lambda表达式封闭的特殊变量。 不幸的是, for循环仍然需要使用特殊的捕捉变量处理。

等待异步任务完成

.NET 4.0中引入的CountdownEvent类封装了很多等待的许多任务的完成所需要的逻辑。 最初级的开发人员使用Thread.Join来电或单个WaitHandle.WaitAll电话。 这些都具有可伸缩性问题。 旧的模式是使用单一ManualResetEvent和信号它当计数器达到零。 该计数器使用更新后的Interlocked类。 CountdownEvent使这种模式更加容易。 不过,别忘了把你的主要的工人,以及避免,如果所有工人已经排队前一个工人完成可能发生微妙的竞争条件。

.NET 4.0还引入了Task ,可以通过具有链连接它的子任务类TaskCreationOptions.AttachedToParent 。 如果你调用Task.Wait上的父,将等待所有子任务完成为好。

生产者-消费者

.NET 4.0引入的BlockingCollection其作用像不同的是当集合为空它可以阻止一个正常队列类。 你可以通过调用排队对象Add ,并通过调用出队的对象TakeTake块直至产品可用。 这大大简化了生产者 - 消费者的逻辑。 它曾经是开发商试图写自己的阻塞队列类的情况。 但是,如果你不知道你在做什么,然后你才能真正搞砸了......坏。 事实上,时间最长的有微软MSDN文档这是本身严重打破了一个阻塞队列的例子。 幸运的是,它已被删除。

与工作者线程进度更新UI

引进BackgroundWorker实现了从WinForm应用程序的开发新手容易得多分拆后台任务。 主要的好处是,你可以调用ReportProgress从内DoWork事件处理程序和ProgressChanged事件处理程序将被自动编组到UI线程。 当然,任何人,跟踪上,所以我的答案,知道我是怎么想编组操作(通过Invoke等)作为更新与简单的进度信息的UI解决方案。 我就可以撕裂一切的时候,因为它通常是一个可怕的做法。 BackgroundWorker仍然迫使开发商为推模式(通过在后台编组操作),但至少它确实这一切的幕后。

调用的inelegance

我们都知道,一个UI元素只能从UI线程访问。 这通常意味着开发者必须通过使用编组作业ISynchronizeInvokeDispatcherObject ,或者SynchronizationContext转移回控制到UI线程。 但是让我们面对它。 这些编组操作看起来很丑陋。 Task.ContinueWith做出这个多了几分优雅,但真正的荣耀去await为C#5的新异步编程模型的一部分。 await可用于等待一个Task以在流动的任务正在运行时,控制被暂时中断,然后在合适的同步上下文非常点返回这样的方式完成。 没有什么更优雅,比使用满意await作为所有这些替代Invoke呼叫。

并行编程

我经常看到询问如何事情可以并行发生的问题。 旧的方式是创建一个线程数或使用ThreadPool 。 .NET 4.0给使用TPL和PLINQ。 该Parallel类是一个伟大的方式得到一个循环并行去的迭代。 和PLINQ的AsParallel是同一枚硬币的普通老LINQ的不同侧面。 这些新功能TPL大大简化这一类的多线程编程的。

.NET 4.5引入的TPL数据流库。 它的目的是让优雅的其他复杂的并行编程的问题。 它通过抽象类成块。 它们可以是目标块或源块。 数据可以从一个块流到另一个。 有许多不同的块,包括BufferBlock<T> BroadcastBlock<T> ActionBlock<T>等所有做不同的事情。 而且,当然,整个库将被用于新的应用进行了优化asyncawait关键字。 这是一个令人兴奋的新的一组类,我觉得会慢慢流行起来。

正常终止

你如何让一个线程停止? 我看到这个问题很多。 最简单的方法是调用Thread.Abort ,但我们都知道这样做的危险...我希望。 有许多不同的方法来安全地做到这一点。 .NET 4.0通过引入一个更加统一的概念,称为消除CancellationTokenCancellationTokenSource 。 后台任务可以查询IsCancellationRequested或只是调用ThrowIfCancellationRequested在安全点,摆好中断他们正在做力所能及的工作。 其他线程可以调用Cancel请求取消。



Answer 2:

那么让我们来看看这里:

  1. ThreadPool类-有点老了,但仍然可靠简单的生产者-消费者模式。
  2. BackgoundWorker (.NET 2.0 +) -另一个老学校建设,用于在GUI应用程序的后台执行任务提供有用的功能。
  3. Timer秒-在使用后台线程指定的时间间隔执行的代码是有用的。
  4. Task类(.NET 4.0 +) -线程是在底层的线程池中运行,并提供了许多有用的功能,如异常编组和调度抽象。 有用的所谓“任务并行”的格局。
  5. Parallel.ForParallel.ForEach (.NET 4.0+) -好为在一组并行数据的执行相同的操作。 有用的所谓“数据并行”的格局。
  6. Parallel.Invoke (.NET 4.0 +) -通过进一步的抽象Task秒。 简单地触发关的代码数块(方法,lambda表达式)并联。
  7. 并发集合(.NET 4.0 +) - 所有你需要在一个有效的,线程安全的方式通过或线程之间共享数据。


Answer 3:

毫无疑问,获得与新交手TPL数据流库(包含在.NET 4.5)会给你在并行开发方面最大的提升。

如果你是认真的高度并行的应用程序,花一两天与数据流熟悉自己。 这是认真做好。



Answer 4:

TaskTask<T>但他们已经在这里以来.NET 4 async不一定与线程工作,看到从ØredevJon的视频进行了很好的解释。



文章来源: What .NET 4.5 (or earlier) higher-level constructs make Threading easier?