2012-05-02 3 views
32

TaskCompletionSource의 목적과 비동기/스레드없는 작업의 관계를 이해하려고합니다. 나는 일반적인 생각을 가지고 있다고 생각하지만 나의 이해가 올바른지 확인하고 싶다.TaskCompletionSource - 스레드가없는 비동기 작업을 이해하려고 시도합니다.

처음에는 TPL (Task Parallel Library)을보고 스레드가없는/비동기 작업을 만들 수있는 좋은 방법이 있는지 알아보기 시작했습니다 (ASP.NET 사이트의 확장 성을 높이기 위해 노력하고 있다고 가정). TPL에 대한 이해는 미래에 매우 중요해 보입니다 (async/await). 어느 날 TaskCompletionSource으로 안내했습니다.

제 생각에 클래스 중 하나에 TaskCompletionSource을 추가하는 것이 실제로 비동기 코딩을 많이하지는 않습니다. 여전히 동기화 코드를 실행중인 경우 코드 호출이 차단됩니다. 나는 이것이 마이크로 소프트 API의 경우조차도 마찬가지라고 생각한다. 예를 들어, WebClient 클래스에서 벗어난 DownloadStringTaskAsync에서 처음에 수행하는 설정/동기화 코드는 차단됩니다. 실행중인 코드는 현재 스레드 또는 일부 스레드에서 실행해야합니다. 그렇지 않으면 새 스레드를 실행해야합니다.

Microsoft에서 async 다른 호출을 호출 할 때 사용자 코드에서 TaskCompletionSource을 사용하므로 클래스 클라이언트가 클래스가 차단하지 않을 새 스레드를 만들지 않아도됩니다.

Microsoft가 비동기 API를 내부적으로 수행하는 방식을 잘 모릅니다. 예를 들어 .Net 4.5에 대해 SqlDataReader에서 벗어난 새로운 async 방법이 있습니다. IO 완료 포트가 있다는 것을 알고 있습니다. 아마도 C# 개발자들이 사용하지 않을 낮은 수준의 추상화 (C++?)라고 생각합니다. 입출력 완료 포트가 데이터베이스 또는 네트워크 호출 (HTTP)에 대해 작동하는지 아니면 파일 입출력에만 사용되는지는 확실하지 않습니다.

질문에 대한 답은 정확합니까? 내가 잘못 표현한 것들이 있습니까?

+0

: 우리는 오류 또는 과도한 자원 소모없이 한 번 에서 이러한 작업 만 시작하여이를 증명할 수 ? –

+0

제 이해가 정확하다면 ... 확실하지 않거나 없습니까? – coding4fun

답변

53

TaskCompletionSource은 코드를 실행하지 않는 Task 개체를 만드는 데 사용됩니다.

마이크로 소프트의 새로운 비동기 API는 I/O 기반 비동기 작업 (또는 타임 아웃과 같은 비 CPU 기반 비동기 작업)이있을 때마다 상당히 많이 사용됩니다. 또한 async Task 메서드를 쓰면 TCS를 사용하여 반환 된 Task을 완료합니다.

Task 인스턴스를 만드는 다양한 방법을 설명하는 블로그 게시물 Creating Tasks가 있습니다. async/await 관점 (TPL 관점이 아님)으로 작성되었지만 여기에도 계속 적용됩니다.

는 또한 스티븐 Toub의 우수한 게시물을 참조하십시오

+0

스티븐 감사합니다.하지만 내부에 대한 올바른 이해가 있습니까? – coding4fun

+1

비동기 메서드에는 비동기 작업을 시작하는 데 사용되는 동기 부분이 있습니다. IIRC, IOCP는 어떤 종류의'HANDLE' 기반 데이터 전송에도 사용될 수 있으며,'비동기 '래핑 방식으로'Begin' /'End' 래핑 된 IOCP 연산을 래핑하는 것은 드문 일이 아닙니다. 'TaskCompletionSource'를 사용하여)'Task'에 저장합니다. –

+0

또한 TaskCompletionSource의 사용법을 이해하려고 노력 중입니다. 코드를 실행하지 않는 작업을하는 이유는 무엇인지 혼란 스럽습니다. 나는 당신의 블로그 포스트를 읽었다. 호출자가 구독 할 수있는 이벤트로 TCS가 사용되는 것 같지만 정기적 인 작업을 사용할 수 있고 작업이 완료 될 때까지 작업을 기다릴 수있는 이유는 무엇입니까? –

4

나는

첫 두 단락은 우리가 본

이하 (죄송합니다, 링크가 순간에 죽을 수)

http://tutorials.csharp-online.net/TaskCompletionSource에 제공 한 설명을 좋아한다 Task.Run이 풀링 된 (또는 풀링되지 않은) 스레드에서 대리인을 실행하는 작업을 만드는 방법 작업을 만드는 또 다른 방법은 TaskCompletionSource입니다.

TaskCompletionSource를 사용하면 나중에 이 시작되고 끝나는 모든 작업에서 작업을 만들 수 있습니다. 작동이 완료되면 또는 결함을 표시하여 수동으로 드라이브하는 "슬레이브" 작업을 제공하여 작동합니다. 이것은 입출력 작업에 이상적입니다. 작업 기간 동안 스레드를 차단하지 않고도 개의 작업 (반환 값, 예외, 및 연속성을 전달할 수있는 능력)을 모두 얻습니다.

TaskCompletionSource를 사용하려면 클래스를 인스턴스화하기 만하면됩니다. 은 을 기다리고 다른 작업과 마찬가지로 계속할 수있는 작업을 반환하는 Task 속성을 제공합니다. 이 작업은, 그러나, 를 통해 TaskCompletionSource 객체에 의해 완전히 제어하는 ​​다음과 같은 방법 : 이러한 방법을 호출

public class TaskCompletionSource<TResult> 
{ 
public void SetResult(TResult result); 
public void SetException (Exception exception); 

public void SetCanceled(); 
public bool TrySetResult (TResult result); 
public bool TrySetException (Exception exception); 
public bool TrySetCanceled(); 
... 
} 

는 오류가 발생한 또는 취소 완료된 로 퍼팅, 작업 신호 상태 (후자는 섹션의 "취소"섹션에 있음). 이 메서드들 중 하나를 정확히 한 번 호출해야합니다. 다시 호출하면 SetResult, SetException 또는 SetCanceled 이 예외를 throw하지만 Try * 메서드는 false를 반환합니다.

다음 예는 5 초 동안 기다린 후 (42) 인쇄 : TaskCompletionSource의 진정한 힘은 스레드를 묶어하지 않는 작업을 만드는 것입니다

var tcs = new TaskCompletionSource<int>(); 
new Thread (() =>  { 
         Thread.Sleep (5000); 
         tcs.SetResult (42); 
         })  
      .Start(); 
Task<int> task = tcs.Task; // Our "slave" task. 
Console.WriteLine(task.Result); // 42 

다른 재미있는 따옴표

.

.. 이상 스레드없이 TaskCompletionSource의

우리는 사용에 연속 시작할 때만 스레드 5 초 후 결합되는 것을 의미한다. 문제는 여기에 무엇을

+0

링크가 작동하지 않습니다. –

+1

좋은 설명 – Ricky

관련 문제