使用任务.在HttpListener,GetContextAsync之后运行或ContinueWith

本文关键字:之后 运行 ContinueWith GetContextAsync 任务 HttpListener | 更新日期: 2023-09-27 18:18:53

以下内容有什么区别(如果有的话):

_listener = new HttpListener();
// Wait for an incoming request, then start a new task
// that executes ProcessContext()
var httpctx = await _listener.GetContextAsync();
await Task.Run(() => ProcessContext(httpctx));
/* -- or -- */
// Use ContinueWith to pass the incoming request to ProcessContext()
await _listener.GetContextAsync().ContinueWith(async (tsk) => {
    if (tsk.Status != TaskStatus.RanToCompletion) Debug.Assert(false);
    await ProcessContext(tsk.Result);
});

第一个方法需要一个笨拙的闭包来将上下文传递给新的Task,仅就这个事实而言,我倾向于认为第二个方法更好。我仍然是新的异步虽然,所以我可能是错的。

总体目标是让一个任务持续等待GetContextAsync的结果:

async Task Listen()
{
    while (_listener != null && _listener.IsListening)
    {
        // Use one of the methods above to get the context
        // and pass that context to a new task. This allows
        // the current task to loop around and immediately
        // resume listening for incoming requests
    }
}

使用任务.在HttpListener,GetContextAsync之后运行或ContinueWith

第一个选项是使用Task.RunProcessContext卸载到ThreadPool线程。第二种选择不会这样做。它只是完成GetContextAsync,然后继续执行ProcessContext

然而,由于ContinueWith不意味着与async-await一起使用,它将同步运行,直到第一次等待,然后两者并行继续,并将控制权返回给调用方法(所以不要混合ContinueWith和async-await)

不清楚为什么这些是你的选择,因为你可以简单地调用这两个方法并等待结果:

var httpctx = await _listener.GetContextAsync();
await ProcessContext(httpctx);

它与使用ContinueWith非常相似(当正确使用时),但它显然更简单。在这里使用Task.Run并没有真正的帮助。它主要用于并行代码或从UI线程卸载。