2012-05-10 2 views
12

대리인은 .NET에서 스레드를 쉽게 만드는 개체 중 일부입니다. reference. 메소드를 비동기 적으로 호출하는 데 사용할 수 있습니다. 스레드를 사용하기가 쉽거나 오류가 발생하기 쉬운 프레임 워크 4.5 (또는 이전 버전)에는 다른 어떤 객체가 있습니까?더 높은 수준의 .NET 4.5 (또는 이전 버전) 구성으로 스레딩을 더 쉽게 만들 수 있습니까?

다른 추상화로 인해 동시성과 멀티 스레드가 더 쉬워 졌습니까?

참고 :이 질문은 this을 업데이트합니다.

+4

대리인 및 이벤트는 스레딩과 관련이 없으며 .NET 4.5에만 국한되지 않습니다. 당신이 무슨 말을하고 있는지 말할 수 없으므로 더 명확히하십시오. –

+0

@JohnSaunders 비동기 대표는 스레딩을 더 쉽게 만듭니다. http://msdn.microsoft.com/en-us/library/22t547yb.aspx – LamonteCristo

+0

대표자의 비동기 사용이 버전 1.0 이후 .NET에 있다는 것을 알고 계셨습니까? –

답변

21

나는 멀티 스레딩과 관련된 많은 질문에 답하는 경향이 있으며, 나는 종종 다양한 기본 질문을 여러 가지 방법으로 묻습니다. 지난 수년간 가장 많이 보았던 문제를 제시하고 최신 기술로 인해 이러한 문제를보다 쉽게 ​​해결할 수있는 방법을 설명합니다. 루프 변수

이 이상 닫기

스레딩에 고유 한 문제가되지 않지만 스레딩의 사용은 확실히 문제를 확대. C# 5.0은 각 반복마다 새 변수를 만들어 foreach 루프에 대해이 문제를 해결합니다. 더 이상 λ 식 클로저를위한 특별한 변수를 생성 할 필요가 없습니다. 불행히도 for 루프는 여전히 특수 캡처 변수로 처리해야합니다.

은 많은 작업의 완료를 기다릴 필요로하는 많은 로직을 캡슐화하는 CountdownEvent 클래스를 도입 비동기 작업

.NET 4.0을 완료하기를 기다리는 중. 대부분의 중학교 개발자는 Thread.Join 전화를 사용하거나 WaitHandle.WaitAll 전화 한 통을 사용했습니다. 이 두 가지 모두 확장 성 문제가 있습니다. 예전의 패턴은 하나의 ManualResetEvent을 사용하고 카운터가 0에 도달했을 때이를 알려주는 것이 었습니다. 카운터는 Interlocked 클래스를 사용하여 업데이트되었습니다. CountdownEvent은이 패턴을 훨씬 쉽게 만듭니다. 모든 근로자가 대기 상태가되기 전에 한 명의 근로자가 끝내면 발생할 수있는 미묘한 경쟁 조건을 피하기 위해 근로자를 주 근로자로 간주해야합니다.

.NET 4.0은 TaskCreationOptions.AttachedToParent을 통해 연결된 자식 작업을 가질 수있는 Task 클래스도 도입했습니다. 부모에게 Task.Wait으로 전화하면 모든 하위 작업도 완료 될 때까지 기다립니다.

생산자 - 소비자

.NET 4.0 컬렉션이 비어있을 때 그것을 차단 수 있다는 점을 제외하고 일반 큐와 같은 역할을하는 BlockingCollection 클래스를 소개했다. Add을 호출하고 Take을 호출하여 개체를 큐에 대기시킬 수 있습니다. Take 항목을 사용할 수있을 때까지 차단합니다. 이렇게하면 생산자 - 소비자 논리가 상당히 단순 해집니다. 개발자는 자신의 블로킹 대기열 클래스를 작성하려고했습니다. 그러나, 당신이 무엇을하고 있는지 당신이 모른다면 당신은 정말로 그것을 망칠 수 있습니다. 실제로 가장 긴 시간 동안 Microsoft는 MSDN 설명서에서 블로킹 큐 예제를 자체적으로 심각하게 손상 시켰습니다. 다행히도 이후 삭제되었습니다. 작업자 스레드 진행

업데이트 UI는 BackgroundWorker의 도입은 초보 개발자를위한 많은 쉽게의 WinForm 응용 프로그램에서 백그라운드 작업을 회전했다. 주요 이점은 DoWork 이벤트 처리기 내에서 ReportProgress으로 호출 할 수 있으며 ProgressChanged 이벤트 처리기는 UI 스레드에 자동으로 마샬링됩니다. 물론, 내 답변을 추적하는 사람은 간단한 진행 정보로 UI를 업데이트하기위한 솔루션으로 (Invoke 등을 통해) 작업 마샬링에 대해 어떻게 생각하는지 알고 있습니다. 나는 그것이 항상 끔찍한 접근이기 때문에 항상 찢어 버린다. BackgroundWorker은 여전히 ​​개발자를 백그라운드에서 마샬링 작업을 통해 밀어 넣기 모델로 만들지 만, 적어도이 모든 것을 백그라운드에서 수행합니다.

우리 모두는 UI 요소는 UI 스레드에서 액세스 할 수 있다는 사실을 알고 호출

의 우미하지 않음. 이것은 일반적으로 개발자가 ISynchronizeInvoke, DispatcherObject 또는 SynchronizationContext을 통해 마샬링 작업을 사용하여 컨트롤을 UI 스레드로 다시 전송해야한다는 것을 의미했습니다. 하지만 얼굴을 보자. 이러한 마샬링 작업은보기 흉한 것처럼 보입니다. Task.ContinueWith은 좀 더 우아하게 만들었지 만 C# 5의 새로운 비동기 프로그래밍 모델의 일부로 await으로 이동했습니다. await은 작업이 실행 중일 때 흐름 제어가 일시적으로 중단 된 다음 오른쪽 동기화 컨텍스트의 바로 그 지점에서 반환되는 방식으로 Task이 완료 될 때까지 대기하는 데 사용할 수 있습니다. Invoke 전화를 대신하여 await을 사용하는 것보다 더 우아하고 만족스러운 것은 없습니다.

병렬 프로그래밍 나는 종종 일이 동시에 일어날 수있는 방법을 질문 물어 볼

. 이전 방법은 스레드를 몇 개 만들거나 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 호출하여 취소를 요청할 수 있습니다.

+0

와우 이것이 내가 필요한 것입니다! 나는 물건의 1,000 피트보기를 위해 도처에보고 있었다. 그리고 이것은 그것이다. 너무 나쁜 사람들은이 질문을 마감했다. 나는 그것을 다시 열기 위해 지명했다. – LamonteCristo

+0

Reactive Extensions (Rx) 및 StreamInsight도이 목록에 있어야합니까? – LamonteCristo

+0

@ makerofthings7 : 아마도 ... 시간이되면 나는 그것을 할 것입니다. –

1
TaskTask<T>

,하지만 그들은 반드시 스레드 작업 아주 좋은 설명 Jon's video from Øredev가 표시되지 않는 .NET 4. async부터 여기 있었어요.

2

의심 할 여지없이 새로운 Tpl DataFlow 라이브러리 (.net 4.5에 포함)를 사용하면 동시 개발 측면에서 가장 큰 향상을 얻을 수 있습니다.

높은 동시성 응용 프로그램을 중요하게 생각한다면 하루나 이틀 동안 DataFlow에 익숙해 지도록하십시오. 그것은 심각하게 좋다.

7

음의 여기 보자 :

  1. ThreadPool 클래스 - 간단한 생산자 - 소비자 패턴 좀 오래된,하지만 여전히 신뢰할.
  2. BackgoundWorker (.NET 2.0 이상) - GUI 응용 프로그램의 백그라운드에서 작업을 실행하는 데 유용한 기능을 제공하는 다른 구형 구조입니다.
  3. Timer s - 백그라운드 스레드를 사용하여 지정된 간격으로 코드를 실행하는 데 유용합니다.
  4. Task 클래스 (.NET 4.0 이상) - 기본 스레드 풀에서 실행되며 예외 마샬링 및 예약과 같은 유용한 기능을 제공하는 스레딩 추상화입니다. 이른바 "작업 병렬 처리"패턴에 유용합니다.
  5. Parallel.For, Parallel.ForEach (.NET 4.0 이상) - 데이터 집합에 대해 동일한 작업을 병렬로 실행하는 데 적합합니다. 소위 "데이터 병렬 처리"패턴에 유용합니다.
  6. Parallel.Invoke (.NET 4.0 이상) - Task 초 이상의 추상화. 병렬로 여러 코드 (메서드, lambdas)를 간단하게 실행합니다.
  7. 동시 수집 (.NET 4.0 이상) - 효율적이며 스레드로부터 안전한 방식으로 스레드간에 데이터를 전달하거나 공유해야하는 모든 기능을 제공합니다.
관련 문제