方法在完成前被另一个线程调用时应该抛出异常

Posted

技术标签:

【中文标题】方法在完成前被另一个线程调用时应该抛出异常【英文标题】: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。 【参考方案1】:

您需要一种不允许重入的同步机制,而Monitor 不是其中之一(它是设计可重入的)。我的建议是使用SemaphoreSlim、which 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();

【讨论】:

以上是关于方法在完成前被另一个线程调用时应该抛出异常的主要内容,如果未能解决你的问题,请参考以下文章

捕获在不同线程中抛出的异常

2017-9-1 - Q - 异常处理 - 多线程基础

2017-9-1 - A - 异常处理 - 多线程基础

C#中用Backgroundworker调用UI的textbox控件,对其赋值,有时会抛出异常。

Java程序中的异常应该在啥时候抛出

JAVA如何抛出异常