【问题标题】:Method should throw an exception when called by another thread before completion方法在完成前被另一个线程调用时应该抛出异常
【发布时间】:2021-09-16 12:54:55
【问题描述】:

我有一个方法StartProcess()。如果另一个线程同时或在调用EndProcess()之前由相同的初始线程调用相同的方法,我希望此方法抛出异常。

我尝试了Monitor 类,但我不确定如何将其应用于上述案例。我看到的与我正在寻找的内容接近的是:

var obj = new Object();

// Define the critical section.
Monitor.Enter(obj);
try {
   // Code to execute one thread at a time.
}
// catch blocks go here.
finally {
   Monitor.Exit(obj);
}

我需要指导来处理我所陈述的确切情况。我一直在尝试一整天,但无法让它发挥作用。

【问题讨论】:

  • 您为什么要这样做?调用该方法的任何人都需要使用他们自己的同步机制来防止遇到您明确抛出的异常,这意味着您要同步两次。如果您要让此操作处理自己的同步,则在获取锁时它应该有预期的行为,无论是等待(同步还是异步)、跳过该部分等。
  • @Servy 假设方法应该处理它的同步,我怎样才能在代码中实现呢?
  • 如果方法应该处理自己的同步,那么它不应该在同时被多个线程调用时抛出,因为您刚刚将其定义为不是异常情况,而是受支持的情况.
  • obj 应该是一个字段以锁定 afaics。

标签: c# multithreading locking


【解决方案1】:

您需要一种不允许重入的同步机制,而Monitor 不是其中之一(它是设计可重入的)。我的建议是使用SemaphoreSlimwhich is not reentrant。这种机制不会查看哪个线程正在调用它。这只是一个简单的计数器。为了在信号量可用时获取信号量,或在信号量不可用时立即返回,您可以使用零 millisecondsTimeout 调用 Wait 方法,如下所示:

SemaphoreSlim semaphore = new SemaphoreSlim(1, 1);
bool acquired = semaphore.Wait(0);
if (!acquired) throw new InvalidOperationException();
try
{
    // Code to execute disallowing concurrency
}
finally
{
    semaphore.Release();
}

【讨论】:

    【解决方案2】:

    您似乎正在寻找 ManualResetEventSlim:

    ManualResetEventSlim resetEvent = new ManualResetEventSlim();
    
    // Block other calls.
    resetEvent.Wait();
    
    // Reset state to block next calls.
    resetEvent.Reset();
    
    try
    {
      // Your code
    }
    finally
    {
      // Set state to allow next call to proceed.
      resetEvent.Set();
    }
    

    【讨论】:

      猜你喜欢
      • 2011-11-14
      • 2016-07-28
      • 2010-12-06
      • 2012-06-04
      • 2012-01-11
      • 1970-01-01
      • 1970-01-01
      • 2023-03-12
      • 2022-01-09
      相关资源
      最近更新 更多