异步方法计时器

时间:2016-03-15 17:14:24

标签: c# .net asynchronous async-await

如果传递给它的函数在X分钟之前没有完成,我需要一个抛出异常的方法。

这是我的原始代码:

public class Poller : IPoller
    {
        public async Task<bool> RunTimedFunction(string taskName, 
                                 int timeoutMs, 
                                 Func<bool> pollMethod)
        {
             var canPoll = true;
             var returnValue = false;
             var watch = System.Diagnostics.Stopwatch.StartNew();

        var t = Task.Factory.StartNew(() =>
        {
            watch.Start();
            returnValue = pollMethod();
            canPoll = false;
            return returnValue;
        });


        while (canPoll)
        {
            if(watch.ElapsedMilliseconds >= timeoutMs)
                throw new TimeoutException(String.Format("Task: {0} has timed out", taskName));
        }
        await t;

        return returnValue;
    }
}

我可以测试它是否适用于以下内容:

    [Test]
    [ExpectedException(typeof(TimeoutException))]
    public async Task  Poller_PollTimeout()
    {
        var name = "Timeout";
        var timeout = 10;
        var func = new Func<bool>(() =>
        {
            Thread.Sleep(1000);
            return true;
        });
        var t = _poller.Poll(name, timeout, func);

        await t.ContinueWith((task) =>
        {
            if (task.Exception != null)
                throw task.Exception.InnerException;
        });
    }

根据我现在提出的建议:

public class Poller : IPoller
{
    public async Task<T> RunTimedFunction<T>(string taskName, 
                                             int timeoutMs, 
                                             Func<T> pollMethod)
    {
        var timerTask = Task.Delay(timeoutMs);
        var funcTask = Task.Run(pollMethod);
        var firstFinished = await Task.WhenAny(timerTask, 
                                               funcTask);

        if(firstFinished == timerTask)
            throw new TimeoutException(String.Format("Task: {0} has timed out", taskName));

        return funcTask.Result;
    }
}

1 个答案:

答案 0 :(得分:3)

怎么样

public async Task<Tuple<int, T>> TimeFunc<T>(
        Func<T> target,
        int timeoutMilliseconds)
{
    var timeoutTask = Task.Delay(timeoutMilliseconds);
    var timer = Stopwatch.StartNew();
    var funcTask = Task.Run(() => target());
    var first = await Task.WhenAny(new[] { timeoutTask, funcTask });
    timer.Stop();

    if (first == timeoutTask)
    {
        throw new TimeoutException();
    }

    return Tuple.Create(timer.ElapsedMilliseconds, funcTask.Result);
}