메소드 내에서 async / await를 사용하고 싶지 않지만 외부에서 await 키워드를 사용할 수 있도록 여전히 "장식"하면 TaskCompletionSource.cs :
public static Task<T> RunAsync<T>(Func<T> function)
{
if (function == null) throw new ArgumentNullException(“function”);
var tcs = new TaskCompletionSource<T>();
ThreadPool.QueueUserWorkItem(_ =>
{
try
{
T result = function();
tcs.SetResult(result);
}
catch(Exception exc) { tcs.SetException(exc); }
});
return tcs.Task;
}
여기 와 여기에서
Tasks와 같은 패러다임을 지원하려면 Task façade를 유지하는 방법과 임의의 비동기 작업을 Task로 참조하는 기능이 필요하지만 기본 인프라의 규칙에 따라 해당 Task의 수명을 제어해야합니다. 비 동시성이고, 비용이 많이 들지 않는 방식으로 그렇게하는 것. 이것이 TaskCompletionSource의 목적입니다.
예를 들어 .NET 소스에서도 사용됩니다. WebClient.cs :
[HostProtection(ExternalThreading = true)]
[ComVisible(false)]
public Task<string> UploadStringTaskAsync(Uri address, string method, string data)
{
// Create the task to be returned
var tcs = new TaskCompletionSource<string>(address);
// Setup the callback event handler
UploadStringCompletedEventHandler handler = null;
handler = (sender, e) => HandleCompletion(tcs, e, (args) => args.Result, handler, (webClient, completion) => webClient.UploadStringCompleted -= completion);
this.UploadStringCompleted += handler;
// Start the async operation.
try { this.UploadStringAsync(address, method, data, tcs); }
catch
{
this.UploadStringCompleted -= handler;
throw;
}
// Return the task that represents the async operation
return tcs.Task;
}
마지막으로 다음 사항도 유용하다는 것을 알았습니다.
나는 항상이 질문을 받는다. 그 의미는 외부 리소스에 대한 I / O 호출을 차단하는 어딘가에 스레드가 있어야한다는 것입니다. 따라서 비동기 코드는 요청 스레드를 비우지 만 시스템의 다른 곳에서는 다른 스레드를 희생해야합니다. 아뇨, 전혀 아닙니다. 비동기 요청이 확장되는 이유를 이해하기 위해 비동기 I / O 호출의 단순화 된 예를 살펴 보겠습니다. 요청이 파일에 기록되어야한다고 가정 해 봅시다. 요청 스레드는 비동기 쓰기 메소드를 호출합니다. WriteAsync는 BCL (Base Class Library)에 의해 구현되며 비동기 I / O에 완료 포트를 사용합니다. 따라서 WriteAsync 호출은 비동기 파일 쓰기로 OS에 전달됩니다. 그런 다음 OS는 드라이버 스택과 통신하여 데이터를 전달하여 I / O 요청 패킷 (IRP)에 씁니다. 이곳은 흥미로운 일입니다. 장치 드라이버가 IRP를 즉시 처리 할 수없는 경우 비동기 적으로 처리해야합니다. 따라서 드라이버는 디스크에 쓰기 시작을 지시하고 OS에 "보류 중"응답을 반환합니다. OS는 해당“보류”응답을 BCL에 전달하고 BCL은 불완전한 작업을 요청 처리 코드로 반환합니다. 요청 처리 코드가 작업을 기다리고 있으며,이 작업은 해당 메소드 등에서 불완전한 작업을 반환합니다. 마지막으로 요청 처리 코드가 완료되지 않은 작업을 ASP.NET으로 반환하고 요청 스레드가 해제되어 스레드 풀로 돌아갑니다. 요청 처리 코드가 작업을 기다리고 있으며,이 작업은 해당 메소드 등에서 불완전한 작업을 반환합니다. 마지막으로 요청 처리 코드가 완료되지 않은 작업을 ASP.NET으로 반환하고 요청 스레드가 해제되어 스레드 풀로 돌아갑니다. 요청 처리 코드가 작업을 기다리고 있으며,이 작업은 해당 메소드 등에서 불완전한 작업을 반환합니다. 마지막으로 요청 처리 코드가 완료되지 않은 작업을 ASP.NET으로 반환하고 요청 스레드가 해제되어 스레드 풀로 돌아갑니다.
ASP.NET의 Async / Await 소개
목표가 응답 성이 아닌 확장 성을 향상시키려는 경우,이를 수행 할 수있는 기회를 제공하는 외부 I / O의 존재에 의존합니다.