使用 Task.Delay() 重置的值创建 Class

Create Class With Value Which Resets using Task.Delay()

我在 C# windows 服务中有一些标志值,我想暂时更改这些值,但一段时间后会自动恢复为默认值。 class 的骨架看起来像这样

public class Revertable<T>
{
    public readonly T DefaultValue;
    public T Value { get; protected set; }

    public async Task SetValue(T newValue, TimeSpan resetDelay)
    {
        Value = newValue;
        await Task.Delay(resetDelay);
        Value = DefaultValue;
    }

    public void ResetValue()
    {
        Value = DefaultValue;
    }
}

一切都很好,但是如果有人再次调用 SetValue,我现在将安排两个中断,这很可能会踩到对方的脚趾。一种想法是简单地拒绝任何试图调用 SetValue if !Value.Equals(DefaultValue) 的请求。这也让人觉得笨拙,但有点管用。但无论如何,我需要有人能够决定随时取消设置该值。

我一直在研究 CancellationTokenSource/CancellationToken 构造,但我正在摸索如何实际设置这一切。似乎我需要向我的 class 添加一个 CancellationTokenSource 成员(ResetValue() 或其他人可以使用),并将其提供给 Task.Delay() 调用。如果有人调用 ResetValue(),令牌源发起取消,我们继续。如此修改后,class 的内部结构将如下所示:

...
private CancellationTokenSource TokenSource;
public async Task SetValue(T newValue, TimeSpan resetDelay)
{
    if (!Value.Equals(DefaultValue))
        return;

    Value = newValue;
    using (CancellationTokenSource src = new CancellationTokenSource())
    {
        TokenSource = src;
        await Task.Delay(resetDelay, src.Token);
    }
    Value = DefaultValue;
}

public void ResetValue()
{
    if (TokenSource != null && TokenSource.Token.CanBeCanceled)
    {
        TokenSource.Cancel();
        TokenSource.Dispose();
    }
    Value = DefaultValue;
}

我对 async 编程有些陌生,我不想完全搞砸做一些看起来应该相对简单的事情(或者留下一堆未处理的令牌源浮动大约)。这看起来是解决这个问题的有效方法吗?或者有人可以建议更好的方法吗?

您根本不需要线程或任务。只需使用时间戳并使用(非自动)属性.

保护您的字段
public class Revertable<T>
{
    public readonly T DefaultValue;
    public readonly TimeSpan ResetDelay;

    private T _currentValue;
    private DateTimeOffset _resetTime;

    public Revertable(T defaultValue, TimeSpan resetDelay)
    {
        this.DefaultValue = defaultValue;
        this.ResetDelay = resetDelay;
        _currentValue = defaultValue;
        _resetTime = DateTimeOffset.MinValue;
    }

    public T Value 
    { 
        get
        {
            return (System.DateTimeOffset.Now > _resetTime)
                ? DefaultValue 
                : _currentValue;
        }
        set
        {
            _currentValue = value;
            _resetTime = System.DateTimeOffset.Now.Add(this.ResetDelay); 
        }
    }
}

public static void Main()
{
    var r = new Revertable<string>("Default value", new TimeSpan(0,0,1));
    Console.WriteLine("Value is now {0}", r.Value);
    r.Value = "Changed";
    for (int i = 0; i<30; i++)
    {
        System.Threading.Thread.Sleep(100);
        Console.WriteLine("Value is now {0}", r.Value);
    }
}

输出:

Value is now Default value
Value is now Changed
Value is now Changed
Value is now Changed
Value is now Changed
Value is now Changed
Value is now Changed
Value is now Changed
Value is now Changed
Value is now Changed
Value is now Default value
Value is now Default value
Value is now Default value
Value is now Default value
Value is now Default value

DotNetFiddle.

上提供完整代码