我经常只想触发一次某个函数,但我需要从另一个被重复调用的函数中触发它。例如,拍摄某些内容的快照供以后使用。我通常通过设置全局布尔值来实现。
我想知道我这样做是否真的是最好的方式?
我似乎记得读过全局变量很糟糕,全局布尔变量更糟糕!
无论如何,这就是我通常只完成一次触发某种方法的方法:
在我的初始变量集中......
private var myStatus:Boolean = false;
然后,在经常被调用的函数中......
if (!myStatus) {
doMyFunction();
myStatus = true;
}
对我来说这似乎是合乎逻辑的,但正确的事情?
UPDATE :根据我从你的答案中学到的东西,我现在首先检查XML节点是否存在(我将图像存储在XML结构中),而不是检查全局布尔变量。在任何写入磁盘之前发生),如果没有,那么我附加一个带有base64编码图像数据的新节点。我仍然设置一个布尔标志,以便稍后我可以用用户编辑的图像数据覆盖空白图像(如果需要)。它完美地运作。谢谢大家的帮助!
我现在对在某些情况下使用该特定(线程不安全)系统感到更自在。
答案 0 :(得分:7)
当你调用一个函数时,它应该按你所期望的那样对你提供的参数做。如果你以完全相同的方式调用函数两次,你应该期望该函数给你相同的结果或做同样的事情。
将此一次调用依赖项移动到多次调用函数的逻辑可能更好。如果您只需要调用该函数一次,则只需调用一次。或者,将不同的参数传递给函数,以表明您正在做一些不同的事情。
答案 1 :(得分:5)
这实际上取决于你的意思。如果您的代码将从多个线程调用,那么您的竞争条件可能意味着可以多次调用doMyFunction
。这是因为多个线程可以检查myStatus
,看到它是假的,然后调用doMyFunction
。您可以先通过设置变量来改善这种情况:
if (!myStatus) {
myStatus = true;
doMyFunction();
}
但这只会缩小窗口的问题,但不能消除它。
要消除竞争条件,您需要锁定。
答案 2 :(得分:4)
在C / C ++中,您通常可以保留doMyFunction()仅在使用静态变量封装后调用的事实,如下所示:
void doMyFunction() {
// gets called only once.
// side effects go here.
}
void functionThatGetsCalledALot() {
static bool called = false;
if (!called) {
doMyFunction();
called = true;
}
// do more stuff
}
这避免了全局变量的使用,但具有相同的效果,并且静态var在相关的地方被声明,因此很明显发生了什么。请注意,这不是线程安全的,因此如果您有线程,则需要锁定。
答案 3 :(得分:2)
这不是线程安全的。这对你来说可能并不重要,但你确实说过“与语言无关”:你可能不希望在Java的通用库中使用这种模式。
这是一个难以用语言无法解决的问题,因为可用的替代方案在很大程度上取决于语言。例如,如果你需要线程安全,你可以在POSIX上获得pthread_once。在C中,你有静态局部变量来从全局范围中获取该布尔值。在任何OO语言中,如果您正在拍摄“某事”的快照供以后使用,那么可能有一个合适的对象对应于“某事物”(或快照),它可以存储该标志。
答案 4 :(得分:0)
我认为你的方法没有错。请记住,并不总是存在“正确”的东西......确实存在一些错误的东西,但正确的东西可能是主观的,并且还可以根据系统的要求而显着依赖。
答案 5 :(得分:0)
我没有看到任何其他方式。关于如何改进这一点,唯一想到的是 - 线程安全。但是,只有在有多个线程调用该函数时才需要这样做。
答案 6 :(得分:0)
在Perl 5.10或更高版本中,您将使用state
变量。
use 5.010;
sub test{
state $once = 1;
if( $once ){
$once = undef;
say 'first';
} else {
say 'not first';
}
}
test for 1..5;
输出
first not first not first not first not first