使用基于秒表的Func作为循环控制变量

时间:2016-01-07 14:46:33

标签: c# while-loop func stopwatch

尝试使用Func<bool>作为循环控制变量如下所示似乎扰乱了Resharper。鉴于以下秒表:

var executionTimeStopwatch = new Stopwatch();
executionTimeStopwatch.Start();

这会引发“循环控制变量永远不会在循环内部更新”警告:

Func<bool> mustStop = () => executionTimeStopwatch.ElapsedMilliseconds < TIMEOUT_MILLISECONDS;
while (!mustStop()) // -> function call
{
    // ...
}

然而,这不是:

Func<bool> mustStop = () => executionTimeStopwatch.ElapsedMilliseconds < TIMEOUT_MILLISECONDS;
var k = false;      // -> declaration
while (!k)          // -> used for loop control
{
    k = mustStop(); // -> explicit update
    // ...
}

我不明白执行这些代码的结果可能有何不同;由于mustStop()取决于秒表,因此每次调用它时都应进行不同的评估。

我错过了什么吗?

2 个答案:

答案 0 :(得分:1)

  

我错过了什么吗?

不,两个代码块都没有区别。事实上,在使用发布模式编译时,编译器将优化第二个块以在大多数情况下删除变量k

Resharper无法证明循环变量在循环内部发生了变化,因为它发生在另一种方法中。简单地说,resharper不够聪明,无法确定mustStop委托在多次调用时是否可能返回不同的值。

在这种情况下,您可以忽略警告或禁止警告。

答案 1 :(得分:1)

这是ReSharper中的一个已知问题,RSRP 451141

  

RSRP-451141内部永远不会更改错误的循环控制变量   环

     

以下代码将生成错误的&#34;循环控制变量   内部循环永远不会改变&#34;:

    /// <summary>
    /// Function will be evaluated on the same thread as the calling thread
    /// </summary>
    /// <param name="function"></param>
    /// <param name="msInterval">Time to wait between each check of function, in ms</param>
    /// <param name="msTimeout"></param>
    /// <param name="timeoutAction"></param>
    /// <returns>true if function eventually returned true, false otherwise</returns>
    public static bool WaitForTrueOnSameThread(Func<bool> function, int msInterval, int msTimeout, Action timeoutAction = null)
    {
        var sw = Stopwatch.StartNew();
        while (!function()) {
            if (sw.ElapsedMilliseconds > msTimeout) {
                timeoutAction?.Invoke();
                return false;
            }
            Wait(msInterval);
        }
        return true;
    }

目前没有明确的修正时间表。

RSRP 429291看起来非常相似。