非阻塞等待条件评估的C#

时间:2020-06-26 11:55:23

标签: c# async-await delay

我有一个类,它具有一个名为ActiveDelay的属性,该类用于定义一个持续时间,在该持续时间内,条件评估应等待之后再检查条件是否仍然为真。属性SetpointA是用于将给定值与之进行比较的值。

下面是我目前正在做的事情

public void EvaluateCondition(T value)
{
    if(value.Equals(SetpointA))
    {
        Task.Delay(ActiveDelay).ContinueWith(_ => EvaluateConditionDelayed(GetValue())).Wait();
    }
}

private void EvaluateConditionDelayed(object value)
{
    if (value.Equals(SetpointA))
    {
        Console.WriteLine("Waited and worked");
    }
    else
    {
        Console.WriteLine("Condition now false");
    }
}

我两次调用函数EvaluateCondition,一次的TimeSpan为5秒,另一次的TimeSpan为2秒,我希望2秒调用应该在5秒调用之前完成,但是实际上会发生什么是5秒钟的电话等待,然后2秒钟的电话等待。

我认为与异步有关,并且在这里等待,但是我没有找到对我有帮助的信息。

我想说的很清楚,这些延迟不应该暂停程序,它们应该只在外部等待,并允许程序的其余部分不受影响地运行。

扩展代码部分

此处是上述内容的详尽版本

public class AlarmCondition
{
    #region Property declaration
    public TimeSpan ActiveDelay { get; set; } // Need to be historised ?
    public TimeSpan ClearDelay { get; set; } // Need to be historised ?
    #endregion

    #region Constructor
    public AlarmCondition() { }

    public AlarmCondition(TimeSpan activeDelay, TimeSpan clearDelay)
    {
        ActiveDelay = activeDelay;
        ClearDelay = clearDelay;
    }
    #endregion

}

public class EqualCondition<T> : AlarmCondition
{
    #region Property declaration
    public T SetpointA { get; }
    #endregion

    #region Constructor
    public EqualCondition() { }

    public EqualCondition(TimeSpan activeDelay, TimeSpan clearDelay) : base(activeDelay, clearDelay)
    {
        SetpointA = setpointA;
    }
    #endregion

    public void EvaluateCondition(T value)
    {
        if(value.Equals(SetpointA))
        {
            Task.Delay(ActiveDelay).ContinueWith(_ => EvaluateConditionDelayed(value));
        }
    }

    private void EvaluateConditionDelayed(T value)
    {
        if (value.Equals(SetpointA))
        {
            Console.WriteLine("Waited and worked");
        }
        else
        {
            Console.WriteLine("Condition now false");
        }
    }
}

// In another file and namespace
public class ConsoleDisplay
{
    public static void Main(string[] args)
    {
        EqualCondition<bool> condition1 = new EqualCondition<bool>(new TimeSpan(0, 0, 5), new TimeSpan(0, 0, 5));
        EqualCondition<bool> condition2 = new EqualCondition<bool>(new TimeSpan(0, 0, 2), new TimeSpan(0, 0, 5));

        condition1.EvaluateCondition(true);
        condition2.EvaluateCondition(true);
    }
}

1 个答案:

答案 0 :(得分:1)

您可以从您的方法中返回Task,以便调用者决定是否要等待结果。例如:

public async Task EvaluateCondition(T value)
{
    if(value.Equals(SetpointA))
    {
        await Task.Delay(ActiveDelay);
        EvaluateConditionDelayed(GetValue());
    }
}

或者,如果您不希望呼叫者拥有做出此类决定的选项,则只需从当前的实现中删除.Wait()(阻止)即可。即使没有该任务,该任务仍应在控制台中打印(如果您的程序运行时间足够长):

public void EvaluateCondition(T value)
{
    if(value.Equals(SetpointA))
    {
        Task.Delay(ActiveDelay).ContinueWith(_ => EvaluateConditionDelayed(GetValue()));
    }
}

UPD

要启动多个EvaluateCondition并等待它们并行完成,可以使用Task.WhenAll

var ev1Task = EvaluateCondition(someVal1);
var ev2Task = EvaluateCondition(someVal2);
await Task.WhenAll(ev1Task, ev2Task);

如果您不想等待,只需跳过await Task.WhenAll(ev1Task, ev2Task)(并修复警告)。

相关问题