programing

Task.Start / Wait와 Async / Await의 차이점은 무엇입니까?

new-time 2020. 5. 6. 22:36
반응형

Task.Start / Wait와 Async / Await의 차이점은 무엇입니까?


뭔가 빠졌을 수도 있지만 차이점은 무엇입니까?

public void MyMethod()
{
  Task t = Task.Factory.StartNew(DoSomethingThatTakesTime);
  t.Wait();
  UpdateLabelToSayItsComplete();
}

public async void MyMethod()
{
  var result = Task.Factory.StartNew(DoSomethingThatTakesTime);
  await result;
  UpdateLabelToSayItsComplete();
}

private void DoSomethingThatTakesTime()
{
  Thread.Sleep(10000);
}

뭔가 빠졌을 수도 있습니다

너는.

일의 차이 무엇

Task.Wait

await task

?

식당에서 웨이터에게 점심을 주문합니다. 당신의 명령을 한 순간, 친구가 들어와 당신 옆에 앉아 대화를 시작합니다. 이제 두 가지 선택이 있습니다. 작업이 완료 될 때까지 친구를 무시할 수 있습니다. 수프가 도착할 때까지 기다렸다가 기다리는 동안 아무 것도 할 수 없습니다. 또는 친구에게 응답 할 수 있으며 친구가 말을 멈 추면 웨이터가 수프를 가져옵니다.

Task.Wait

작업이 완료 될 때까지 차단-작업이 완료 될 때까지 친구를 무시합니다.

await

메시지 대기열에서 메시지 처리를 유지하고 작업이 완료되면 "대기 후 중단 한 부분을 선택합니다"라는 메시지를 대기열에 넣습니다. 친구와 대화를 나누고 대화가 중단되면 수프가 도착합니다.


여기에 Eric의 대답을 보여주는 코드가 있습니다.

public void ButtonClick(object sender, EventArgs e)
{
  Task t = new Task.Factory.StartNew(DoSomethingThatTakesTime);
  t.Wait();  
  //If you press Button2 now you won't see anything in the console 
  //until this task is complete and then the label will be updated!
  UpdateLabelToSayItsComplete();
}

public async void ButtonClick(object sender, EventArgs e)
{
  var result = Task.Factory.StartNew(DoSomethingThatTakesTime);
  await result;
  //If you press Button2 now you will see stuff in the console and 
  //when the long method returns it will update the label!
  UpdateLabelToSayItsComplete();
}

public void Button_2_Click(object sender, EventArgs e)
{
  Console.WriteLine("Button 2 Clicked");
}

private void DoSomethingThatTakesTime()
{
  Thread.Sleep(10000);
}

이 예는 차이점을 매우 명확하게 보여줍니다. async / await를 사용하면 호출 스레드가 차단되지 않고 계속 실행됩니다.

static void Main(string[] args)
{
    WriteOutput("Program Begin");
    // DoAsTask();
    DoAsAsync();
    WriteOutput("Program End");
    Console.ReadLine();
}

static void DoAsTask()
{
    WriteOutput("1 - Starting");
    var t = Task.Factory.StartNew<int>(DoSomethingThatTakesTime);
    WriteOutput("2 - Task started");
    t.Wait();
    WriteOutput("3 - Task completed with result: " + t.Result);
}

static async Task DoAsAsync()
{
    WriteOutput("1 - Starting");
    var t = Task.Factory.StartNew<int>(DoSomethingThatTakesTime);
    WriteOutput("2 - Task started");
    var result = await t;
    WriteOutput("3 - Task completed with result: " + result);
}

static int DoSomethingThatTakesTime()
{
    WriteOutput("A - Started something");
    Thread.Sleep(1000);
    WriteOutput("B - Completed something");
    return 123;
}

static void WriteOutput(string message)
{
    Console.WriteLine("[{0}] {1}", Thread.CurrentThread.ManagedThreadId, message);
}

DoAsTask 출력 :

[1] 프로그램 시작
[1] 1-시작
[1] 2-작업 시작
[3] A-시작한 것
[3] B-무언가를 완성 함
[1] 3-작업 완료 결과 : 123
[1] 프로그램 끝

DoAsAsync 출력 :

[1] 프로그램 시작
[1] 1-시작
[1] 2-작업 시작
[3] A-시작한 것
[1] 프로그램 끝
[3] B-무언가를 완성 함
[3] 3-작업 완료 결과 : 123

업데이트 : 출력에 스레드 ID를 표시하여 예제를 개선했습니다.


In this example, not much, practically. If you are awaiting a Task that returns on a different thread (like a WCF call) or relinquishes control to the operating system (like File IO), await will use less system resources by not blocking a thread.


Wait(), will cause to run potentially async code in sync manner. await will not.

For example, you have an asp.net web application. UserA calls /getUser/1 endpoint. asp.net app pool will pick a thread from thread pool (Thread1) and, this thread will make a http call. If you do Wait(), this thread will be blocked until http call resolves. While it is waiting, if UserB calls /getUser/2, then, app pool will need to serve another thread (Thread2) to make http call again. You just created (Well, fetched from app pool actually) another thread for no reason, because you cannot use Thread1 it was blocked by Wait().

If you use await on Thread1, then, SyncContext will manage sync between Thread1 and http call. Simply, it will notify once http call is done. Meanwhile, if UserB calls /getUser/2, then, you will use Thread1 again to make http call, because it was released once await got hit. Then another request can use it, even further more. Once http call is done (user1 or user2), Thread1 can get the result and return to caller (client). Thread1 was used for multiple tasks.


In the example above, you can use "TaskCreationOptions.HideScheduler", and greatly modify the "DoAsTask" method. The method itself is not asynchronous, as it happens with "DoAsAsync" because it returns a "Task" value and is marked as "async", making several combinations, this is how it gives me exactly the same as using "async / await":

static Task DoAsTask()
{
    WriteOutput("1 - Starting");
    var t = Task.Factory.StartNew<int>(DoSomethingThatTakesTime, TaskCreationOptions.HideScheduler); //<-- HideScheduler do the magic

    TaskCompletionSource<int> tsc = new TaskCompletionSource<int>();
    t.ContinueWith(tsk => tsc.TrySetResult(tsk.Result)); //<-- Set the result to the created Task

    WriteOutput("2 - Task started");

    tsc.Task.ContinueWith(tsk => WriteOutput("3 - Task completed with result: " + tsk.Result)); //<-- Complete the Task
    return tsc.Task;
}

참고URL : https://stackoverflow.com/questions/9519414/whats-the-difference-between-task-start-wait-and-async-await

반응형