我如何接受任务<T>并设置超时? [英] How do I take a Task<T> and put a timeout on it?

查看:34
本文介绍了我如何接受任务<T>并设置超时?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的另一个问题基本上需要这个,所以我想我会在这里分享我的通用解决方案.

My other question basically needed this so I thought I would share my generic solution here.

我在处理 HttpClient Tasks 时遇到了问题,基本上无法完成 Web 请求;所以程序或线程挂起.我需要一种简单的方法来为任务添加超时,以便它正常返回或在超时先到期时返回取消.

I had trouble with HttpClient Tasks for web requests basically never completing; so the program or thread hangs. I needed a simple way to add a timeout to a task, so that it returns normally or returns cancelled if the timeout expires first.

可以在此处找到一些替代方法:http://blogs.msdn.com/b/pfxteam/archive/2011/11/10/10235834.aspx

Some alternative approaches can be found here: http://blogs.msdn.com/b/pfxteam/archive/2011/11/10/10235834.aspx

推荐答案

从技术上讲,您不能接受任务并在一段时间后强制取消它.您可以做的最好的事情是创建一个新任务,该任务将在给定的时间段后标记为已取消,或者在其他任务按时完成时完成.

You technically can't take a task and force it to be canceled after some period of time. The best that you can do is create a new task that will be marked as canceled after the given period of time, or will be completed when the other task is if it finishes in time.

需要注意的一个关键点是,操作超时并不会阻止任务继续执行它的工作,它只是在达到超时时提前"触发这个新任务的所有继续.

A key point to note is that the operation timing out doesn't stop the task from continuing on with it's work, it just fires off all continuations of this new task "early" if the timeout is reached.

由于使用了 CancellationToken,这样做非常简单:

Doing this is pretty trivial, thanks to the use of CancellationToken:

var newTask = task.ContinueWith(t => { }
    , new CancellationTokenSource(timeoutTime).Token);

我们可以将此模式与 WhenAny 结合起来,以轻松确保任何异常都能正确传播到延续.还需要一份有/没有结果的任务副本:

We can combine this patter with WhenAny to easily ensure that any exceptions are properly propagated through to the continuation. A copy for tasks with/without a result is also needed:

public static Task WithTimeout(Task task, TimeSpan timeout)
{
    var delay = task.ContinueWith(t => { }
        , new CancellationTokenSource(timeout).Token);
    return Task.WhenAny(task, delay).Unwrap();
}
public static Task<T> WithTimeout<T>(Task<T> task, TimeSpan timeout)
{
    var delay = task.ContinueWith(t => t.Result
        , new CancellationTokenSource(timeout).Token);
    return Task.WhenAny(task, delay).Unwrap();
}

这篇关于我如何接受任务&lt;T&gt;并设置超时?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆