等待TaskEx.Delay

mak*_*mak 3 c# asynchronous

我正在玩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();
    }
}
Run Code Online (Sandbox Code Playgroud)

当3个客户端同时连接时,我期望以下输出

Client connected 1
Client connected 2
Client connected 3
<5000ms pause>
Response 1
Response 2
Response 3
Run Code Online (Sandbox Code Playgroud)

相反,我得到了

Client connected 1
<5000ms pause>
Response 1
Client connected 2
<5000ms pause>
Response 2
Client connected 3
<5000ms pause>
Response 3
Run Code Online (Sandbox Code Playgroud)

如果我使用延续,它就像我预期的那样工作

int c = counter;
TaskEx.Delay(5000, cts.Token).ContinueWith(t => {
    Console.WriteLine("Response " + c);
    // send response
});
Run Code Online (Sandbox Code Playgroud)

我的印象是await TaskEx.Delay立即返回(并将继续while (!cts.IsCancellationRequested)),而while块的其余部分将是5000ms之后的延续.所以它应该与我的代码相同.ContinueWith,不是吗?

Jon*_*eet 5

TaskEx.Delay将立即返回任务,但您在再次呼叫之前正在等待该任务listener.GetContextAsyncTask().该来电者(Start)会尽快你打第一继续await未已经完成的声明,但内部Listen方法,它的同步码的出现-这是await.

词汇的剩余部分不是在连续出现时发生的词汇 - 它是"方法执行的剩余部分".换句话说,该方法有效地"暂停" await,但允许呼叫者继续.