[c#] 어떻게하면 C #에서 비동기 메서드를 만들 수 있습니까?


0 Answers

자신의 메서드 내에서 async / await를 사용하고 싶지는 않지만 외부의 TaskCompletionSource.cs 에서 await 키워드를 사용할 수 있도록 여전히 "장식"하고 TaskCompletionSource.cs 다음을 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; 
}

여기here

Tasks에서 이러한 패러다임을 지원하려면 Task façade를 유지하는 방법과 임의의 비동기 작업을 Task로 지칭하는 기능이 필요합니다.하지만 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에 대한 소개

목표가 응답 성보다는 확장 성을 향상시키는 것이라면,이를 수행 할 수있는 기회를 제공하는 외부 I / O의 존재에 의존합니다.

Question

내가 읽은 모든 블로그 게시물은 C #에서 비동기 메서드를 사용하는 방법을 알려주지 만, 이상한 이유로 인해 자신의 비동기 메서드를 작성하는 방법을 설명하지 않습니다. 그래서 저는 지금이 방법을 사용하는 코드를 가지고 있습니다 :

private async void button1_Click(object sender, EventArgs e)
{
    var now = await CountToAsync(1000);
    label1.Text = now.ToString();
}

CountToAsync 이 메서드를 작성했습니다.

private Task<DateTime> CountToAsync(int num = 1000)
{
    return Task.Factory.StartNew(() =>
    {
        for (int i = 0; i < num; i++)
        {
            Console.WriteLine("#{0}", i);
        }
    }).ContinueWith(x => DateTime.Now);
}

이, Task.Factory , 비동기 메서드를 작성하는 가장 좋은 방법의 사용, 또는 내가 다른 방법으로 이것을 작성해야합니까?




Related