等待TaskEx.Delay
我正在玩HttpListener和Async CTP
class HttpServer : IDisposable { HttpListener listener; CancellationTokenSource cts; public void Start() { listener = new HttpListener(); listener.Prefixes.Add("http://+:1288/test/"); listener.Start(); cts = new CancellationTokenSource(); Listen(); } public void Stop() { cts.Cancel(); } int counter = 0; private async void Listen() { while (!cts.IsCancellationRequested) { HttpListenerContext context = await listener.GetContextAsyncTask(); // my extension method with TaskCompletionSource and BeginGetContext Console.WriteLine("Client connected " + ++counter); // simulate long network i/o await TaskEx.Delay(5000, cts.Token); Console.WriteLine("Response " + counter); // send response } listener.Close(); } }
当3个客户端同时连接时,我期望以下输出
Client connected 1 Client connected 2 Client connected 3 Response 1 Response 2 Response 3
相反,我得到了
Client connected 1 Response 1 Client connected 2 Response 2 Client connected 3 Response 3
如果我使用延续,它就像我预期的那样工作
int c = counter; TaskEx.Delay(5000, cts.Token).ContinueWith(t => { Console.WriteLine("Response " + c); // send response });
我的印象是await TaskEx.Delay
立即返回(并将转到while (!cts.IsCancellationRequested)
)并且while块的其余部分将是5000ms之后的延续。 所以它应该与我的代码相同.ContinueWith
,不是吗?
TaskEx.Delay将立即返回一个任务,但是在再次调用listener.GetContextAsyncTask()
之前,您正在等待该任务。 一旦你点击第一个尚未完成的await
语句, 调用者 ( Start
)将继续,但在 Listen
方法中,它具有同步代码的外观 – 这就是await
点 。
词法的其余部分不是在连续出现时发生的词汇 – 它是“方法执行的剩余部分”。 换句话说,该方法在await
有效地“暂停”,但允许调用者继续。
我想出了如何完成我想要做的事情(即使用await
而不是.ContinueWith
和委托):
private async void Listen() { while (!cts.IsCancellationRequested) { HttpListenerContext context = await listener.GetContextAsyncTask(); Console.WriteLine("Client connected " + ++counter); ProcessRequest(context, counter); } listener.Close(); } private async void ProcessRequest(HttpListenerContext context, int c) { await TaskEx.Delay(5000, cts.Token); Console.WriteLine("Response " + c); }