如何触发一次,只有一次...?

时间:2008-12-09 22:59:23

标签: language-agnostic loops boolean

我经常只想触发一次某个函数,但我需要从另一个被重复调用的函数中触发它。例如,拍摄某些内容的快照供以后使用。我通常通过设置全局布尔值来实现。

我想知道我这样做是否真的是最好的方式?

我似乎记得读过全局变量很糟糕,全局布尔变量更糟糕!

无论如何,这就是我通常只完成一次触发某种方法的方法:

在我的初始变量集中......

private var myStatus:Boolean = false;

然后,在经常被调用的函数中......

if (!myStatus) {
    doMyFunction();
    myStatus = true;
}

对我来说这似乎是合乎逻辑的,但正确的事情

UPDATE :根据我从你的答案中学到的东西,我现在首先检查XML节点是否存在(我将图像存储在XML结构中),而不是检查全局布尔变量。在任何写入磁盘之前发生),如果没有,那么我附加一个带有base64编码图像数据的新节点。我仍然设置一个布尔标志,以便稍后我可以用用户编辑的图像数据覆盖空白图像(如果需要)。它完美地运作。谢谢大家的帮助!

我现在对在某些情况下使用该特定(线程不安全)系统感到更自在。

7 个答案:

答案 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