什么.NET 4.5(或更早)更高级别的结构使线程更容易? [英] What .NET 4.5 (or earlier) higher-level constructs make Threading easier?
问题描述
代表有几个,使线程更容易在.NET 参考对象。它们可用于异步调用的方法。在框架4.5(或更早),使使用更容易或更不容易出错的线程什么其他的对象是否存在?
Delegates are a few of the objects that make threading easier in .NET reference. They can be used to asynchronously invoke a method. What other objects exist in framework 4.5 (or earlier) that make the use of threads easier or less error prone?
什么是其他抽象使并发和多线程更容易?
What are the other abstractions make concurrency and multithreading easier?
注:此问题的更新这
推荐答案
我倾向于回答了很多有关多线程问题,我经常看到要求以各种不同的方式相同的基本问题。我将present最常见的问题,因为我看到他们多年来并解释新技术方面取得了解决这些问题更容易。
I tend to answer a lot of questions related to multithreading and I often see the same basic question asked in various different ways. I will present the most common problems as I have seen them over the years and explain how the newer technologies have made solving these problems easier.
关闭了循环变量
这是不特定线程的问题,而是使用线程的绝对放大的问题。 C#5.0修复了这个问题的的foreach
通过为每个迭代一个新的变量循环。您将不再需要创建的lambda EX pression封闭的特殊变量。不幸的是,为
循环将仍然需要一个特殊的捕捉变量处理。
This is not a problem specific to threading, but the use of threading definitely magnifies the problem. C# 5.0 fixes this problem for the foreach
loop by creating a new variable for each iteration. You will no longer have to create a special variable for lambda expression closures. Unfortunately, the for
loop will still need to be handle with a special capturing variable.
等待异步任务完成
.NET 4.0引入了 CountdownEvent
类,它封装了很多等待完成许多任务所需的逻辑。最初级的开发人员使用的Thread.join
来电或单个 WaitHandle.WaitAll的
通话。两者都具有可扩展性的问题。旧的模式是使用单个的ManualResetEvent
,并表示它当计数器达到零。使用互锁
类的柜台进行了更新。 CountdownEvent
使这种模式更加容易。不过,别忘了把你的主要的工人,以及避免,如果一个工人完成所有的工作人员都被排队之前,可以发生的微妙的竞争状态。
.NET 4.0 introduced the CountdownEvent
class which encapsulates a lot of the logic required to wait for the completion of many tasks. Most junior developers used Thread.Join
calls or a single WaitHandle.WaitAll
call. Both of these have scalability problems. The old pattern was to use a single ManualResetEvent
and signal it when a counter reached zero. The counter was updated using the Interlocked
class. CountdownEvent
makes this pattern much easier. Just remember to treat your main as a worker as well to avoid that subtle race condition that can occur if one worker finishes before all workers have been queued.
.NET 4.0还引入了工作
类,可以有子任务,通过 TaskCreationOptions.AttachedToParent
链连接起来。如果你调用 Task.Wait
在家长会等待所有子任务完成为好。
.NET 4.0 also introduced the Task
class which can have child tasks chained off of it via TaskCreationOptions.AttachedToParent
. If you call Task.Wait
on a parent it will wait for all child tasks to complete as well.
生产者 - 消费者
.NET 4.0引入了 BlockingCollection
类,它的作用相似,但它可以在集合为空阻止正常的队列。你可以通过调用添加
和出队的对象,通过调用以
排队的对象。 以
块,直至产品可用。这简化生产者 - 消费者的逻辑相当。它曾经是,开发商试图写自己的阻塞队列类的情况。但是,如果你不知道你在做什么,然后你就可以真正搞砸了......坏。事实上,时间最长微软已经在MSDN文档本身是严重打破了阻塞队列的例子。幸运的是,它已被删除。
.NET 4.0 introduced the BlockingCollection
class which acts like a normal queue except that it can block when the collection is empty. You can queue an object by calling Add
and dequeue an object by calling Take
. Take
blocks until an item is available. This simplifies producer-consumer logic considerably. It used to be the case that developers were trying to write their own blocking queue class. But, if you do not know what you are doing then you can really screw it up...bad. In fact, for the longest time Microsoft had a blocking queue example in the MSDN documentation that was itself badly broken. Fortunately, it has since been removed.
更新UI与工作线程的进步
的BackgroundWorker
的引入实现了从WinForm应用程序的开发新手轻松了许多分拆后台任务。主要的好处是,你可以调用 ReportProgress
从的DoWork
事件处理程序,并在 ProgressChanged
的事件处理程序将被自动编组到UI线程。当然,任何人跟踪我的回答对SO知道我的感受(通过调用
等)作为更新用简单的进度信息的用户界面解决方案编组作业。我撕裂它所有的时间,因为它通常是一个可怕的方式。 的BackgroundWorker
仍然会强制开发商成为推模式(通过编组在后台操作),但至少它做这一切的幕后。
The introduction of BackgroundWorker
made spinning off a background task from a WinForm application a lot easier for novice developers. The main benefit is that you can call ReportProgress
from within the DoWork
event handler and the ProgressChanged
event handlers will be automatically marshaled onto the UI thread. Of course, anyone that tracks my answers on SO knows how I feel about marshaling operations (via Invoke
or the like) as a solution for updating the UI with simple progress information. I rip on it all the time because it is generally a terrible approach. BackgroundWorker
still forces the developer into a push model (via marshaling operations in the background), but at least it does all of this behind the scenes.
调用的inelegance
我们都知道,一个UI元素只能从UI线程访问。这通常意味着,开发人员必须使用通过 ISynchronizeInvoke
, DispatcherObject的
编组作业,或的SynchronizationContext
来控制转移回UI线程。但是让我们面对它。这些编组操作看起来很丑陋。 Task.ContinueWith
做这一点更优雅,但真正的荣耀去等待
作为部分C#5的新的异步编程模型。 等待
可以用来等待工作
以这样的方式来完成流控制,而任务暂时中断正在运行,然后在正确的同步背景下,非常当场退回。没有什么更优雅和满足比使用等待
,以替换那些调用
的电话。
We all know that a UI element can only be accessed from the UI thread. This generally meant that a developer had to use marshaling operations via ISynchronizeInvoke
, DispatcherObject
, or SynchronizationContext
to transfer control back to the UI thread. But lets face it. These marshaling operations look ugly. Task.ContinueWith
made this a little more elegant, but the real glory goes to await
as part of C# 5's new asynchronous programming model. await
can be used to wait for a Task
to complete in such a manner that flow control is temporarily interrupted while the task is running and then returned at that very spot in the right synchronization context. There is nothing more elegant and satisfying than using await
as a replacement for all those Invoke
calls.
并行编程
我经常看到的问题,询问事情如何可以并行发生。旧的方式是创建一个线程数,或使用线程池
。 .NET 4.0给了使用TPL和PLINQ。该并行
类是一个伟大的方式得到一个循环将并行的迭代。而PLINQ的进行AsParallel
是同一枚硬币的老式LINQ的不同侧面。这些新的第三方物流的功能大大简化了这一类多线程编程的。
I often see questions asking how things can happen in parallel. The old way was to create a few threads or use the ThreadPool
. .NET 4.0 gave use the TPL and PLINQ. The Parallel
class is a great way to get the iterations of a loop going in parallel. And PLINQ's AsParallel
is a different side of the same coin for plain old LINQ. These new TPL features greatly simplify this category of multithreaded programming.
.NET 4.5引入了TPL数据流库。它的目的是让优雅的其他复杂的并行编程问题。它通过抽象类成块。它们可以是目标块或源块。数据可以从一个模块流向另一个。有许多不同的区块,包括 BufferBlock< T>
, BroadcastBlock< T>
, ActionBlock< T>
等,所有做不同的事情。当然,整个库将被用于新的进行了优化异步
和等待
关键字。这是一个令人兴奋的新组类,我觉得会慢慢流行起来。
.NET 4.5 introduces the TPL Data Flow library. It is intended to make elegant an otherwise complex parallel programming problem. It abstracts classes into blocks. They can be target blocks or source blocks. Data can flow from one block to another. There are many different blocks including BufferBlock<T>
, BroadcastBlock<T>
, ActionBlock<T>
, etc. that all do different things. And, of course, the whole library will be optimized for use with the new async
and await
keywords. It is an exciting new set of classes that I think will slowly catch on.
正常终止
你如何让一个线程停止?我看到这个问题有很多。最简单的方法是调用 Thread.Abort的
,但我们都知道这样做的危险...我希望。有许多不同的方法来安全地做到这一点。 .NET 4.0中引入了一个通过的CancellationToken
更统一的概念,称为消除和 CancellationTokenSource
。后台任务可以查询 IsCancellationRequested
或只是叫 ThrowIfCancellationRequested
在安全点,摆好中断的任何工作,他们在做什么。其他线程可以调用取消
来请求取消。
How do you get a thread to stop? I see this question a lot. The easiest way is to call Thread.Abort
, but we all know the perils of doing this...I hope. There are many different ways to do this safely. .NET 4.0 introduced a more unified concept called cancellation via CancellationToken
and CancellationTokenSource
. Background tasks can poll IsCancellationRequested
or just call ThrowIfCancellationRequested
at safe points to gracefully interrupt whatever work they were doing. Other threads can call Cancel
to request cancellation.
这篇关于什么.NET 4.5(或更早)更高级别的结构使线程更容易?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!