C# 当对象未锁定时,Monitor.TryEnter返回false

C# 当对象未锁定时,Monitor.TryEnter返回false,c#,.net,multithreading,task-parallel-library,circuit-breaker,C#,.net,Multithreading,Task Parallel Library,Circuit Breaker,我正在我们的服务中实施断路器。它是相当标准的断路器,除了它将所有动作都封装在超时中,因此当发生太多超时时,它也会断开电路。 当断路器处于半开状态时,我使用MonitorTryEnter方法确保只有一个线程执行操作(检查服务是否恢复)。请查找下面的代码段(这是在半开放状态下执行的代码): 编辑(粘贴整个功能代码) 编辑半开放式实现: private bool HalfOpen() { var isHalfOpen = _circuitBreakerState

我正在我们的服务中实施断路器。它是相当标准的断路器,除了它将所有动作都封装在超时中,因此当发生太多超时时,它也会断开电路。 当断路器处于半开状态时,我使用
MonitorTryEnter
方法确保只有一个线程执行操作(检查服务是否恢复)。请查找下面的代码段(这是在半开放状态下执行的代码):

编辑(粘贴整个功能代码)

编辑半开放式实现:

private bool HalfOpen()
        {
            var isHalfOpen = _circuitBreakerStateManager.GetLastStateChangedDate() + _options.BreakDuration < DateTime.UtcNow;
            if (isHalfOpen)
                _circuitBreakerStateManager.SetState(CircuitBreakerState.HalfOpen);
            return isHalfOpen;
        }
private bool half open()
{
var ishalfound=\u circuitBreakerStateManager.GetLastStateChangedDate()+\u options.BreakDuration
我非常担心在异步代码中使用此选项。除非在每个调用此的位置都有一个单线程同步上下文,否则最终可能会调用Monitor.Exit,而不是调用Monitor.TryEnter的线程。一般来说,锁和异步不能很好地结合。@mjwills很抱歉,我在阅读了一些内容后补充说,它可能会有所帮助,但一般来说,如果您尝试使用
lock()
语句,而不是
Monitor.TryEnter
,编译器将发出错误“wait不能在锁体中使用”,您本可以避免这个问题。与其重写为非异步,不如使用上面评论中提到的异步锁之一。@MajkeloDev:您确定
Monitor.Exit
没有抛出,而不仅仅是没有看到异常吗?但是是的,我希望它也能扔出去。
public class TimeoutableCircuitBreaker: ICircuitBreaker
{
    private readonly object _halfOpenSyncObject = new object();    
    ...
private bool HalfOpen()
        {
            var isHalfOpen = _circuitBreakerStateManager.GetLastStateChangedDate() + _options.BreakDuration < DateTime.UtcNow;
            if (isHalfOpen)
                _circuitBreakerStateManager.SetState(CircuitBreakerState.HalfOpen);
            return isHalfOpen;
        }