如何在 C# 中阻止函数调用?
这个函数被不同的类重复调用。我想把它锁起来,这样在我执行当前操作之前没有人可以使用它。然后,我想再次发布它。
请帮忙..
谢谢
编辑:我实际上并没有使用线程......但我正在使用重复调用该函数的计时器,并且它也在不同的类之间被调用。
使用lock
:
private static object lockObject = new object();
lock(lockObject) {
// ... code goes here...
}
如果您从多个线程访问此函数,则需要某种同步。
如果我们谈论的是单线程代码,为什么不使用布尔值来存储您的函数当前是否“可用”?
更新:
正如您添加的那样,您没有使用线程,IMO 一个简单的 bool 就足够了。
如果您需要更多状态,您可以创建一个枚举并相应地设置它。
根据您使用的计时器,您可能正在使用线程。UI 计时器 (Windows.Forms.Timers) 仅在 UI 线程上运行,因此不会被重入调用。但是,System.Threading 计时器使用线程池线程,因此您的代码可以在不同的线程上重入调用 - 在这种情况下,您需要一些线程同步(锁)。
如果您不使用线程,那么只有在执行导致自身被调用的某些事情时,才能重新调用您的代码。最明显的情况是它调用自身时,但不太明显的是应用某些操作会导致一系列事件导致您的方法再次被调用的情况——“反馈循环”。
所以,第一步是问“我的代码是否被可重入调用?”
第二步是问“为什么?”
然后,如果您的代码导致重入,“我怎样才能改变我的代码的操作,使其不会调用自己”。
或者,如果它是线程化的,“我应该在哪里加锁以确保一次只有一个线程可以执行此代码?”
您声明您没有使用线程。如果确实如此,那么函数应该不可能被多次调用,除非你的代码块做了一些可能导致重入的事情。
我注意到这里的其他答案之一建议使用 lock 语句。请注意,这仅在真正的问题是您从多个线程调用该函数时才有效。如果问题实际上是您有一个线程,但正在执行导致重新进入函数的操作(例如,抽取 UI 消息队列),则 lock 语句不会阻止代码执行多次 - 这是因为 lock 语句允许同一线程上的递归锁——即它只禁止来自不同线程的并发访问。
因此,注意到您提到了计时器的使用,您的特定情况将取决于您使用的计时器类型 - 如果您使用 System.Threading 命名空间中的计时器,那么锁可能就是您想要的(因为你实际上是在不同的线程上执行代码,因为这个计时器使用线程池来执行你的回调)。但是,如果您使用的是 System.Windows.Forms 命名空间中的计时器,那么您使用的是始终使用 UI 线程(通过处理 UI 消息队列)执行的计时器,在这种情况下,很可能是您的问题有是某种重入问题。
如果问题是可重入性,并且您没有从不同的线程调用代码,那么您应该能够只使用布尔变量来记录您已经在函数中的时间,而不是一个不起作用的锁,并禁止重入.
话虽如此,如果您确实有这种类型的重入,您的设计可能会出现问题。
请注意,人们有时没有考虑到计时器的一件事是,当您仍在执行因先前触发计时器而产生的操作时,是否可以再次触发计时器。为了避免这种情况,我个人很少将定时器设置为重复触发——而是将其设置为仅触发一次,然后在处理响应触发器执行的操作结束时重新启用定时器。这意味着持续时间(没有调整)成为处理最后一个触发操作的结束和下一个触发操作开始之间的间隔。
通常虽然这实际上是您想要的,因为您不希望在前一个操作尚未完成时触发相同的操作。
标准的做法是抛出一个 InvalidOperationException,向您的代码客户端发出您的类对象尚未处于可用状态的信号。