我可能错过了一些东西,但做的和做的有什么区别:

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);
}

当前回答

为了演示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] Program Begin
[1] 1 - Starting
[1] 2 - Task started
[3] A - Started something
[3] B - Completed something
[1] 3 - Task completed with result: 123
[1] Program End

DoAsAsync输出:

[1] Program Begin
[1] 1 - Starting
[1] 2 - Task started
[3] A - Started something
[1] Program End
[3] B - Completed something
[3] 3 - Task completed with result: 123

更新:通过在输出中显示线程ID来改进示例。

我可能遗漏了什么

你。

做任务之间有什么区别。等待任务?

你从餐厅的服务员那里点了午餐。你点完餐后不久,一位朋友走进来,坐在你旁边,开始和你聊天。现在你有两个选择。你可以无视你的朋友,直到任务完成——你可以等到你的汤上来,在等待的时候什么也不做。或者你可以回应你的朋友,当你的朋友停止说话时,服务员会给你端来汤。

的任务。等待块,直到任务完成——你忽略你的朋友,直到任务完成。Await继续处理消息队列中的消息,当任务完成时,它将一条消息编入队列,该消息表示“在等待之后从您离开的地方重新开始”。你和你的朋友聊天,当谈话中断时,汤端上来了。

Wait(),将导致以同步方式运行潜在的异步代码。等待不会。

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().

如果你在Thread1上使用await,那么SyncContext将管理Thread1和http调用之间的同步。简单地说,它将在http调用完成后通知。同时,如果UserB调用/getUser/2,那么,你将再次使用Thread1进行http调用,因为它在await被命中时被释放。然后另一个请求可以使用它,甚至更多。一旦http调用完成(user1或user2), Thread1就可以获得结果并返回给调用方(客户端)。Thread1用于多个任务。

在这个例子中,实际上没有太多。如果你正在等待一个Task在不同的线程上返回(比如WCF调用),或者放弃对操作系统的控制(比如File IO), 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);
}