뭔가 빠졌을 수도 있지만 차이점은 무엇입니까?
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를 표시하여 예제를 개선했습니다.
답변
Wait ()는 잠재적으로 비동기 코드를 동기화 방식으로 실행합니다. 기다리지 않습니다.
예를 들어 asp.net 웹 응용 프로그램이 있습니다. UserA는 / getUser / 1 엔드 포인트를 호출합니다. asp.net 앱 풀은 스레드 풀 (Thread1)에서 스레드를 선택하고이 스레드는 http 호출을 수행합니다. Wait ()를 수행하면 http 호출이 해결 될 때까지이 스레드가 차단됩니다. 기다리는 동안 UserB가 / getUser / 2를 호출하면 앱 풀은 다른 스레드 (Thread2)를 제공하여 http를 다시 호출해야합니다. Thread1을 사용할 수 없으므로 Wait ()에 의해 차단 되었기 때문에 방금 다른 스레드를 만들었습니다 (실제로 앱 풀에서 가져 왔습니다).
Thread1에서 await를 사용하면 SyncContext가 Thread1과 http 호출 간의 동기화를 관리합니다. 간단히 말하면 http 호출이 완료되면 알립니다. 한편 UserB가 / getUser / 2를 호출하면 Thread1을 다시 사용하여 http 호출이 이루어집니다. 그런 다음 다른 요청이 더 많은 것을 사용할 수 있습니다. http 호출이 완료되면 (user1 또는 user2) Thread1은 결과를 가져 와서 호출자 (클라이언트)에게 리턴 할 수 있습니다. Thread1은 여러 작업에 사용되었습니다.
답변
이 예에서는 실용적이지 않습니다. 다른 스레드 (예 : WCF 호출)를 반환하거나 파일 IO와 같은 운영 체제에 대한 제어 권한을 포기하는 작업을 기다리는 경우 대기는 스레드를 차단하지 않아 시스템 리소스를 덜 사용합니다.
답변
위의 예에서 “TaskCreationOptions.HideScheduler”를 사용하고 “DoAsTask”메소드를 크게 수정할 수 있습니다. “작업”값을 반환하고 “비동기”로 표시되어 여러 조합을 수행하기 때문에 “DoAsAsync”에서 발생하므로 메소드 자체는 비동기식이 아닙니다. “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;
}