【问题标题】:Use Task.Run or ContinueWith after HttpListener,GetContextAsync?在 HttpListener、GetContextAsync 之后使用 Task.Run 还是 ContinueWith?
【发布时间】:2015-10-21 20:09:04
【问题描述】:

以下之间有什么区别(如果有的话):

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

第一种方法需要一个笨拙的闭包来将上下文传递给新任务,仅凭这一点我倾向于认为第二种方法更好。不过,我仍然是异步的新手,所以我可能是错的。

总体目标是让任务持续等待 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
    }
}

【问题讨论】:

    标签: c# .net async-await task-parallel-library httplistener


    【解决方案1】:

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

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

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

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

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

    【讨论】:

    • 为了扩展一点,我需要将上下文传递给一个新任务,以便当前任务(执行 GetContextAsync)可以立即再次调用 GetContextAsync。然后我可以将 GetContextAsync 放入一个循环中,以不断有一个 Task 等待传入的请求。我在我的问题中添加了更多代码来说明。
    • @RileyGodard 看来您正在寻找调度员,对吧? GetContextAsync 得到一个上下文,然后你想触发 ProcessContext 并调用 GetContextAsync 来接收下一个?如果是这样,请使用您的第一个选项,但无需等待 Task.Run 任务(并确保 ProcessContext 在内部处理异常
    • 在这种情况下awaiting Task.Run 的含义是什么?好奇。
    • @RileyGodard 你的意思是不等待?
    • 是的。我测试了await Task.Run 和简单的Task.Run,似乎没有区别。
    猜你喜欢
    • 1970-01-01
    • 2015-05-09
    • 2014-05-29
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多