gpt4 book ai didi

c# - 检查控制变量后调用 AutoResetEvent.WaitOne

转载 作者:太空宇宙 更新时间:2023-11-03 17:49:33 26 4
gpt4 key购买 nike

想象一下,我有一个类,它的方法可以被多个线程访问。想象一下,该类包含一个整数“i”作为私有(private)字段,并且一些方法会增加/减少该值。

最后想象一下我的一个方法每次 i == 5 时都需要阻塞(使用 AutoResetEvent)

我会写:

if(i == 5)
myAutoResetEvent.WaitOne()

但是如果在我检查“i”的值和我调用 WaitOne 的那一刻之间,另一个线程已经改变了“i”怎么办?

我不能用 lock 包装代码阻止,因为如果 myAutoResetEvent 未发出信号,它将永远保持阻止状态。

有什么解决办法吗?
谢谢

最佳答案

您指定的行为类似于 CountdownEvent ,但是 CountdownEvent不允许计数器为负数(因此初始化为 5 的 CountdownEvent 无法解决问题......)

Joe Albahari 实现了 CountdownEvent template可以通过一些更改来解决您的问题:

public class EqualsWaitHandle
{
private readonly object _locker = new object();

private readonly int _lockValue;
public int Value { get; private set; }

public EqualsWaitHandle(int lockValue = 0, int initialCount = 0)
{
Value = initialCount;
_lockValue = lockValue;
}

public void Signal() { AddCount(-1); }

public void AddCount(int amount)
{
lock (_locker)
{
Value += amount;
if (Value != _lockValue)
Monitor.PulseAll(_locker);
}
}

public void Wait()
{
lock (_locker)
while (Value == _lockValue)
Monitor.Wait(_locker);
}
}

由于 i 之间存在相关性和等待请求(你不应该违反 SRP ......),最好将其作为一个对象进行管理......

顺便说一句,如果您不想将此类/合并到您的类中,您可以使用 ManualResetEventSlim 来实现该行为:
public void AddToVal(int num)
{
lock (_syncObj)
{
_i += num;
if (_i == 5)
{
_event.Reset();
return;
}

_event.Set();
}
}

// and in the waitable thread:
_event.wait();

除非 _i,否则该事件不会被阻止等于 5...

关于c# - 检查控制变量后调用 AutoResetEvent.WaitOne,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37466201/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com