Programming

C #에서 비동기 메소드를 어떻게 작성합니까?

procodes 2020. 5. 18. 21:15
반응형

C #에서 비동기 메소드를 어떻게 작성합니까?


내가 읽은 모든 블로그 게시물은 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비동기 메소드를 작성하는 가장 좋은 방법입니까, 아니면 다른 방법으로 작성해야합니까?


StartNew복잡한 수준이 필요 하지 않으면 권장하지 않습니다 .

비동기 메소드가 다른 비동기 메소드에 종속되는 경우 가장 쉬운 방법은 async키워드 를 사용하는 것입니다 .

private static async Task<DateTime> CountToAsync(int num = 10)
{
  for (int i = 0; i < num; i++)
  {
    await Task.Delay(TimeSpan.FromSeconds(1));
  }

  return DateTime.Now;
}

비동기 메소드가 CPU 작업을 수행하는 경우 다음을 사용해야합니다 Task.Run.

private static async Task<DateTime> CountToAsync(int num = 10)
{
  await Task.Run(() => ...);
  return DateTime.Now;
}

async/ await소개가 도움 이 될 수 있습니다.


메소드 내부에서 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 get asked this question all the time. The implication is that there must be some thread somewhere that’s blocking on the I/O call to the external resource. So, asynchronous code frees up the request thread, but only at the expense of another thread elsewhere in the system, right? No, not at all. To understand why asynchronous requests scale, I’ll trace a (simplified) example of an asynchronous I/O call. Let’s say a request needs to write to a file. The request thread calls the asynchronous write method. WriteAsync is implemented by the Base Class Library (BCL), and uses completion ports for its asynchronous I/O. So, the WriteAsync call is passed down to the OS as an asynchronous file write. The OS then communicates with the driver stack, passing along the data to write in an I/O request packet (IRP). This is where things get interesting: If a device driver can’t handle an IRP immediately, it must handle it asynchronously. So, the driver tells the disk to start writing and returns a “pending” response to the OS. The OS passes that “pending” response to the BCL, and the BCL returns an incomplete task to the request-handling code. The request-handling code awaits the task, which returns an incomplete task from that method and so on. Finally, the request-handling code ends up returning an incomplete task to ASP.NET, and the request thread is freed to return to the thread pool.

Introduction to Async/Await on ASP.NET

If the target is to improve scalability (rather than responsiveness), it all relies on the existence of an external I/O that provides the opportunity to do that.

참고URL : https://stackoverflow.com/questions/16063520/how-do-you-create-an-asynchronous-method-in-c

반응형