【问题标题】:C# function that checks predicate检查谓词的 C# 函数
【发布时间】:2018-10-19 11:01:38
【问题描述】:

我正在编写一个函数,该函数接收要满足的条件和超时,并在满足条件或超时时完成。

这是我目前所拥有的:

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

它适用于简单的布尔值,但我想这样称呼它:

CheckWithTimeout(myValue > 10, 500)

当 myValue 大于 10 或经过 500 毫秒时它会返回(在这种情况下返回 false)

我检查了一下,我认为 Func 是我需要的,但是.. 我找不到合适的例子。 此外,如果有现有的方法来实现这一点,我肯定会更喜欢它。

【问题讨论】:

标签: c# timeout predicate


【解决方案1】:

对于结果和等待,最好使用单独的任务。

    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 更好,因为它不会阻塞)

编辑:带有函数或谓词的示例

【讨论】:

  • 如何调用谓词方法?
  • 谓词测试一组标准的输入。因此,如果您的谓词是 var isOddYear = new Predicate(date => date.Year % 2 == 1);并且您想测试当前年份,您的调用将是: var result = CheckWithTimeout(isOddYear, DateTime.Today, 500);
  • 听起来比 Func 版本更冗长.. 为什么首选它?
  • 标题说你要检查谓词(测试一组标准的值)。因此,您应该提供谓词和要测试的值。为了这个问题,超时延迟。如果你只想执行一个返回布尔值的函数,你不需要谓词重载。
  • 我如何等待方法并获取布尔值。我不能使用 await,因为我的 UT 不能异步
【解决方案2】:

如果您使用简单的bool 参数,则在调用该方法时只会计算一次。如果要多次执行评估,需要使用Func&lt;bool&gt;

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

现在您可以使用 lambda 调用该方法:

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

或者只是创建一个返回 bool 的方法并传入其名称。

【讨论】:

  • 也可以使用'pre-rolled'谓词
  • 欢迎 :) 你能评价一下预卷的东西吗?
  • 这里有 1 个问题:问题说明“...或 500 毫秒过去...”。在这种情况下,您将始终等待 500 毫秒。因此,即使没有必要,您也会等待完全超时。
  • pre-rolled Predicate 类型不存在,只有 Predicate 类型。所以这里需要做更多的工作,请参阅下面的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-15
  • 1970-01-01
  • 2018-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多