如何在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();
}