如何在C#中判断类方法当前是否正在执行

如何在C#中判断类方法当前是否正在执行,c#,multithreading,C#,Multithreading,假设我有以下代码(请假设所有适当的导入语句): 公共类CTestClass{ //性质 保护对象锁; 公共词典第1部分; 受保护系统。定时器。定时器1; //方法 公共测试类(){ LockObj=新对象(); Prop_1=新的ConcurrentDictionary(); 项目1.TryAdd(“关键1”、“价值1”); Timer_1=新的System.Timers.Timer(); 计时器1.Interval=(1000*60);//一分钟 Timer_1.appeased+=新的Ela

假设我有以下代码(请假设所有适当的导入语句):

公共类CTestClass{
//性质
保护对象锁;
公共词典第1部分;
受保护系统。定时器。定时器1;
//方法
公共测试类(){
LockObj=新对象();
Prop_1=新的ConcurrentDictionary();
项目1.TryAdd(“关键1”、“价值1”);
Timer_1=新的System.Timers.Timer();
计时器1.Interval=(1000*60);//一分钟
Timer_1.appeased+=新的ElapsedEventHandler((s,t)=>方法_2());
定时器_1.Enabled=真;
}//结束CTestClass()
公共作废方法_1(){
//做一些需要阅读Prop_1的事情
//但是不要锁定1号道具
}//结束方法_1()
公共无效方法_2(){
锁(LockObj){
//仅当_uu*方法_1()当前未执行时,才使用Prop_1*uu执行某些操作
}
}//结束方法_2()
}//结束CTestClass
//主类
公共课程{
公共静态void Main(字符串[]Args){
CTestClass TC=新的CTestClass();
可并行枚举。范围(0,10)
.ForAll(s=>{
TC.Method_1();
});
}
}
我知道可以使用MethodBase.GetCurrentMethod,但是(除了对全局变量进行杂乱的簿记之外)可以不经思考解决问题吗

提前感谢您的帮助

编辑

(a) 更正了LockObj范围内的错误

(b) 补充一点说明(摘自我下面的评论)

我已经更正了我的代码(在我的实际项目中),并将LockObj作为类属性。问题是,方法2实际上是由System.Timers.Timer启动的,当它准备启动时,很可能方法1已经在执行了。但是在这种情况下,在继续执行方法2之前,等待方法1完成执行是很重要的

我同意,我试图创建的最低限度的工作示例并没有明确说明后一点。让我看看是否可以编辑MWE

代码编辑完成

最后一次编辑


我使用的是Visual Studio 2010和.NET 4.0,因此我没有使我的生活更轻松的异步/等待功能。

如上所述,您应该更熟悉.NET中存在的不同功能。

通过反射或分析谁是concurent-running方法并不能解决这些问题,而是通过使用一个信令原语,它会通知任何感兴趣的人该方法正在运行/结束。

首先,ConcurentDictionary是线程安全的,所以不需要为生成/使用而锁定。因此,如果只关心访问字典,就不需要额外的锁定。 但是,如果您只需要排除方法1和2的执行,那么应该将lock对象声明为类成员,并且可以使用它锁定每个函数体,但是正如我所说的,如果您要使用ConcurentDictionary,则不需要。
如果您真的需要在每一时刻执行哪个方法,您可以使用每个线程的堆栈帧,但这会很慢,我认为在这种情况下没有必要这样做。

您要寻找的术语是。在.NET中实现这一点的方法有很多。
您发现的其中一个(
lock

一般来说,lock对象应该可以被所有需要它的线程访问,并在任何线程尝试锁定它之前进行初始化

lock()
语法确保该锁对象一次只能继续一个线程。试图锁定同一对象的任何其他线程都将停止,直到它们能够获得锁为止

无法超时或以其他方式取消等待锁的操作(除非终止线程或进程)

举个例子,这里有一个更简单的形式:

public class ThreadSafeCounter
{
    private object _lockObject = new Object();  // Initialise once
    private int count = 0; 
    public void Increment()
    {
        lock(_lockObject) // Only one thread touches count at a time
        { 
            count++; 
        }
    } 
    public void Decrement()
    {
        lock (_lockObject) // Only one thread touches count at a time
        {
            count--; 
        }
    } 
    public int Read()
    {
        lock (_lockObject) // Only one thread touches count at a time
        {
            return count; 
        }
    }
}

你可以把这看作是经典读者/作者问题的一种变体,读者不消费作者的产品。我想你可以通过一个int变量和三个互斥来实现

一个互斥锁(mtxExecutingMeth2)保护Method2的执行,并阻止Method2和Method1的执行。Method1必须立即释放它,因为否则就不能有Method1的其他并行执行。但这意味着您必须告诉Method2何时有Method1正在执行,这是通过使用mtxThereAreMeth1互斥来完成的,该互斥仅在没有更多Method1正在执行时才会释放。这由numMeth1的值控制,该值必须由另一个互斥锁(mtxNumMeth1)保护

我没有尝试过,所以我希望我没有引入一些比赛条件。无论如何,它至少应该给你一个可能的方向的想法

这是代码:

protected int numMeth1 = 0;
protected Mutex mtxNumMeth1 = new Mutex();
protected Mutex mtxExecutingMeth2 = new Mutex();
protected Mutex mtxThereAreMeth1 = new Mutex();


public void Method_1() 
{
    // if this is the first execution of Method1, tells Method2 that it has to wait
    mtxNumMeth1.WaitOne();
    if (numMeth1 == 0)
        mtxThereAreMeth1.WaitOne();
    numMeth1++;
    mtxNumMeth1.ReleaseMutex();
    // check if Method2 is executing and release the Mutex immediately in order to avoid 
    // blocking other Method1's
    mtxExecutingMeth2.WaitOne();
    mtxExecutingMeth2.ReleaseMutex();

    // Do something that requires Prop_1 to be read
    // But *__do not__* lock Prop_1

    // if this is the last Method1 executing, tells Method2 that it can execute
    mtxNumMeth1.WaitOne();
    numMeth1--;
    if (numMeth1 == 0)
        mtxThereAreMeth1.ReleaseMutex();
    mtxNumMeth1.ReleaseMutex();
} 

public void Method_2() 
{
    mtxThereAreMeth1.WaitOne();
    mtxExecutingMeth2.WaitOne();

    // Do something with Prop_1 *__only if__* Method_1 () is not currently executing

    mtxExecutingMeth2.ReleaseMutex();
    mtxThereAreMeth1.ReleaseMutex();
} 

听起来你应该读一下和。它类似于lock,只是您对它有更多的控制。为什么要锁定一个局部变量?!在“我不知道”上阅读更多关于该主题的信息,如果不设置一个标志,说明它正在进行中,然后在完成后取消设置标志,你怎么能做到这一点而不进行反思。也许我误解了…我是新来并行枚举的,所以这可能是一个愚蠢的问题,但是为什么要锁定局部变量?谢谢你指出LockObj范围的错误。我现在已经改正了。请查看问题以了解更多信息。为成为一个伟大的答案提供示例。我认为他需要在他的目标上多做一些努力,似乎他正在为标准制作人consuemr工作,但我不能从他的示例中确定。我已经更正了我的代码(在我的实际项目中),并将LockObj作为类属性。问题是,方法2实际上是由System.Timers.Timer启动的,当它准备启动时,很可能会遇到
protected int numMeth1 = 0;
protected Mutex mtxNumMeth1 = new Mutex();
protected Mutex mtxExecutingMeth2 = new Mutex();
protected Mutex mtxThereAreMeth1 = new Mutex();


public void Method_1() 
{
    // if this is the first execution of Method1, tells Method2 that it has to wait
    mtxNumMeth1.WaitOne();
    if (numMeth1 == 0)
        mtxThereAreMeth1.WaitOne();
    numMeth1++;
    mtxNumMeth1.ReleaseMutex();
    // check if Method2 is executing and release the Mutex immediately in order to avoid 
    // blocking other Method1's
    mtxExecutingMeth2.WaitOne();
    mtxExecutingMeth2.ReleaseMutex();

    // Do something that requires Prop_1 to be read
    // But *__do not__* lock Prop_1

    // if this is the last Method1 executing, tells Method2 that it can execute
    mtxNumMeth1.WaitOne();
    numMeth1--;
    if (numMeth1 == 0)
        mtxThereAreMeth1.ReleaseMutex();
    mtxNumMeth1.ReleaseMutex();
} 

public void Method_2() 
{
    mtxThereAreMeth1.WaitOne();
    mtxExecutingMeth2.WaitOne();

    // Do something with Prop_1 *__only if__* Method_1 () is not currently executing

    mtxExecutingMeth2.ReleaseMutex();
    mtxThereAreMeth1.ReleaseMutex();
}