C # функция, которая проверяет предикат - PullRequest
0 голосов
/ 19 октября 2018

Я кодирую функцию, которая получает условие, которое должно быть выполнено, и время ожидания, и оно завершается, когда условие выполняется или оно истекает.

Это то, что я до сих пор:

public static bool CheckWithTimeout(bool toBeChecked, int msToWait)
{
    //var src = CancellationSource
    var task = Task.Run(()=> {
        while (!toBeChecked)
        {
            System.Threading.Thread.Sleep(25);
        }                    
    });
    if (task.Wait(TimeSpan.FromMilliseconds(msToWait)))
        return toBeChecked;
    else
        return false;
}

Это хорошо работает для простых bools, но я хотел бы назвать его следующим образом:

CheckWithTimeout(myValue > 10, 500)

И он вернется, когда myValue больше десяти или пройдено 500 мс (и возвращает false вэто дело)

Я проверил и думаю, что Func - это то, что мне нужно, но .. Я не могу найти подходящий пример.Кроме того, если для этого уже существует метод, я бы определенно предпочел его.

Ответы [ 2 ]

0 голосов
/ 19 октября 2018

Лучше использовать отдельные задачи для результата и ожидания.

    private async Task<bool> CheckWithTimeout(Func<bool> toBeChecked, int msToWait)
    {
        var waitTask = Task.Delay(msToWait);
        var checkTask = Task.Run(toBeChecked);
        await Task.WhenAny(waitTask, checkTask);
        return checkTask.IsCompleted && await checkTask;
    }


    private async Task<bool> CheckWithTimeout<T>(Predicate<T> toBeChecked, T predicateParameter, int msToWait)
    {
        var waitTask = Task.Delay(msToWait);            
        var checkTask = Task.Run(() => toBeChecked(predicateParameter));
        await Task.WhenAny(waitTask, checkTask);
        return checkTask.IsCompleted && await checkTask;
    }

Таким образом, вам не нужно ждать таймаута.(И Taks.Delay лучше, чем Task.Wait, потому что он не блокирует)

Редактировать: пример с функцией или предикатом

0 голосов
/ 19 октября 2018

Если вы используете простой параметр bool, он будет оценен только один раз при вызове метода.Если вы хотите выполнить оценку несколько раз, вам нужно использовать Func<bool>:

public static bool CheckWithTimeout(Func<bool> toBeChecked, int msToWait)
{
    //var src = CancellationSource
    var task = Task.Run(()=> {
        while (!toBeChecked())
        {
            System.Threading.Thread.Sleep(25);
        }                    
    });
    if (task.Wait(TimeSpan.FromMilliseconds(msToWait)))
        return toBeChecked();
    else
        return false;
}

Теперь вы можете использовать лямбду для вызова метода:

CheckWithTimeout(() => myValue > 10, 500)

Или просто создатьметод, который возвращает bool и передает его имя.

...