9

async关键字导致CIL更改(即使方法内部没有等待),但主要是允许await存在。为什么我的TCS不等待?

但我没想到的是以下情况发生:

static void Main(string[] args) 
{ 
    Task t = Go(); 
    t.Wait(); 
} 

static async Task Go() 
{ 
    Console.WriteLine(1); 
    await AAA(3000); 
    Console.WriteLine(2); 
} 


static Task<object> AAA(int a) // <--- No `async` 
{ 
    TaskCompletionSource<object> tcs = new TaskCompletionSource<object>(); 
    Task.Delay(a).ContinueWith(b => tcs.SetResult(null)); 
    return tcs.Task; 
} 

本刊:

1 
(wait) 
2 

但是,如果我改变

static Task<object> AAA(int a) 

static async Task<object> AAA(int a) 

它打印:

1 
2 
(no wait) 

问题

为什么我看不到延迟? TCS仅在三秒后解决。同时,任务没有解决,应该等待。

+2

我认为[razor118](http://stackoverflow.com/a/32785865/477420)答案是问题的最佳演示 - 更改'静态任务 AAA(int a)'到'静态任务 AAA( int a)'(对代码进行必要的更改)并添加'async'。 –

+0

是的,我被咬了,现在想起它 - 这是一个愚蠢的问题。每个异步方法的结果都返回一些东西 - 某个东西被一个任务包装。所以在这里,我实际上正在返回'任务' –

+1

愚蠢或不是你的呼叫,但肯定是教育(和写得很好)。两种版本的代码(异步/非异步)看起来似乎是合理的,并且让我感到困惑(我根据选票投注了足够多的人)。 –

回答

8

如果没有async关键字,您将返回TaskCompletionSource的任务AAA,等待它完成(这将在延迟完成后发生)。

但是,当您添加async关键字时,该方法返回的任务是状态机的任务,该任务将同步完成。该任务在其中(因此)TaskCompletionSource的任务,但这不是你正在等待的任务。

如果你想这种方式来等待TaskCompletionSource的任务,你可以等待的Task<Task>内任务:

await ((Task) await AAA(3000)); 

或者等待TaskCompletionSource的并没有返回它:

async Task AAA(int a) 
{ 
    TaskCompletionSource<object> tcs = new TaskCompletionSource<object>(); 
    Task.Delay(a).ContinueWith(b => tcs.SetResult(null)); 
    await tcs.Task; 
} 

甚至更​​好,只是等待Task.Delay本身:

async Task<object> AAA(int a) 
{ 
    await Task.Delay(a); 
    return null; 
} 
6

因为当你从一个返回类型为Task<object>的异步方法返回Task你得到它Task<Task>与你的任务(你期待等待)里面。那你应该怎么做:

static async Task<object> AAA(int a) 
{ 
    await Task.Delay(a); 
    return null; 
} 

总之,尽量避免在一种方法中混合异步等待和直接任务操作。

2

由于SERG提到的,看看下面这个例子在Visual Studio:

 static async Task<int> AAA(int a) // <--- No `async` 
     { 
      TaskCompletionSource<int> tcs = new TaskCompletionSource<int>(); 
      Task.Delay(a).ContinueWith(b => 
      { 
        tcs.SetResult(1); 
      }); 
      return tcs.Task; 
     } 

你会得到错误是这样的:

因为这是一个异步方法,返回表达式的类型必须是“诠释”的而不是'任务',因为你的方法会同步运行。这就是为什么它需要返回int,而不是Task

+2

关于你的最后一个知识产权,方法*将*运行异步,它需要返回一个'int'而不是'Task ',但方法同步运行的事实isn '*为什么*他必须返回'int'。他需要返回一个'int',因为所有'async'方法都将返回的值包装在'Task'中。该方法将同步运行是真实的,但不是该错误的原因。 – Servy

+0

razor118,这个答案会很棒,因为评论 - 使用一些强类型而不是“Object”会使错误非常明显。或者你可以通过应用@Servy的评论来清理它。 –

+0

Serv as as know async keyword is responsible to inform compiler to build state machine。它不包含返回类型到任务。再看那 私有静态无效测试(){} 和 私有静态异步无效TestAsync(){} – razor118

相关问题