Простой метод Timeout, который принимает Func <T>, не ожидает - PullRequest
0 голосов
/ 07 марта 2019

Я пытаюсь создать простой метод многократного использования, который будет полностью асинхронным. По какой-то причине мой метод Timeout не ожидается, и я озадачен, почему.

    [Fact]
    public async void TestTimeOut()
    {
        Stopwatch sw = Stopwatch.StartNew();
        var Thrown = false;
        try
        {
            await TimeOut(() => Task.Delay(5000), TimeSpan.FromMilliseconds(1000));
        }
        catch(OperationCanceledException ex)
        {
            //** Never Hit
            Thrown = true;
        }
        sw.Stop();

        Assert.True(sw.Elapsed >= TimeSpan.FromMilliseconds(1000)); //** fails nothing is awaited, executes in less than 40ms

        Assert.True(Thrown); //** Fails
    }

    private async Task<T> TimeOut<T>(Func<T> method, TimeSpan timeOut)
    {
        using (var ctsForTask = new CancellationTokenSource())
        {
            var taskTimeOut = Task.Delay(timeOut);
            Task<T> task = Task.Run(() => method(), ctsForTask.Token);
            if (task != await Task.WhenAny(task, taskTimeOut))
            {
                ctsForTask.Cancel();
                throw new OperationCanceledException(ctsForTask.Token);
            }
            return task.Result;
        }
    }

Ответы [ 2 ]

5 голосов
/ 07 марта 2019

Timeout ожидается, но () => Task.Delay(5000) лямбда - нет.Так как Task.Run не знает, что T является Task, он возвращается немедленно.Вместо этого используйте Func<Task<T>> или Func<Task>.

0 голосов
/ 07 марта 2019

Используйте параметр Func<Task<T>> method и дождитесь результата в методе тайм-аута

...