Como acionar uma função uma vez, e apenas uma vez ...?

votos
6

Eu muitas vezes querem desencadear uma determinada função apenas uma vez, mas eu preciso provocá-lo a partir de dentro de outra função que é chamada repetidamente. Por exemplo, tirar um instantâneo de algo para uso posterior. Eu costumo fazê-lo através da criação de um boolean global.

Eu estou querendo saber se a maneira que eu faço é realmente melhor maneira?

Eu me lembro de ler que as variáveis ​​globais são ruins, e variáveis ​​booleanas globais são ainda piores!

Enfim, esta é a forma como eu costumo fazer disparar um determinado método apenas uma vez:

Na minha primeira série de variáveis ​​...

private var myStatus:Boolean = false;

Então, dentro da função que é chamado muitas vezes ...

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

Parece bastante lógico para mim, mas é a coisa certa ?

ATUALIZAÇÃO : Bem, com base no que eu aprendi com as suas respostas, em vez de verificar uma variável booleana global, agora primeiro verificar se existe o nó XML (eu sou armazenar as imagens dentro de uma estrutura XML antes de qualquer escrito para o disco ocorre), e, se isso não acontecer, então eu acrescentar um novo nó com os base64 codificados dados de imagem. Eu ainda definir um sinalizador booleano para que mais tarde eu posso substituir a imagem em branco com dados de imagem editados usuário, se necessário. Funciona perfeitamente. Obrigado a todos por sua ajuda!

Eu agora também se sentir mais confortável sobre o uso esse sistema em particular (thread inseguro) em determinadas situações.

Publicado 09/12/2008 em 23:59
fonte usuário
Em outras línguas...                            


7 respostas

votos
0

Não vejo nada de errado com a sua abordagem aqui. Tenha em mente que nem sempre é a coisa "direita" ... há definitivamente coisas erradas, mas o que é certo pode ser subjetiva, e pode também dependem dramaticamente com base nos requisitos do sistema.

Respondeu 10/12/2008 em 00:02
fonte usuário

votos
0

Eu não vejo nenhuma outra maneira. A única coisa que vem à mente sobre como melhorar este é - a segurança do thread. Mas isso é apenas necessário se você tiver múltiplas threads chamar a função.

Respondeu 10/12/2008 em 00:06
fonte usuário

votos
5

Ela realmente depende exatamente o que você quer dizer. Se o seu código será chamado a partir de mais de um segmento, então você tem uma condição de corrida que poderia significar que doMyFunctionpoderia ser chamado muitas vezes. Isso ocorre porque mais de um thread pode verificar myStatus, vemos que ela é falsa, então invocar doMyFunction. Você pode melhorar a situação um pouco definindo a variável de primeira:

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

mas isso só reduz a janela para os problemas, não eliminá-lo.

Para eliminar a condição de corrida, você precisa de um bloqueio.

Respondeu 10/12/2008 em 00:06
fonte usuário

votos
2

Não é thread-safe. Isso pode não importa para você, mas você disse "linguagem-agnóstico": você provavelmente não iria querer usar esse padrão em uma biblioteca de uso geral para Java.

Esta é uma pergunta difícil de responder de uma forma de linguagem agnóstico, porque as alternativas disponíveis dependem muito da linguagem. Por exemplo em POSIX você tem pthread_once se precisar de fios de segurança. Em C você tem variáveis ​​locais estáticas para obter esse boolean fora do escopo global. Em qualquer linguagem OO, se você está tomando um instantâneo de "algo" para uso posterior, então pode haver um objeto apropriado correspondente ao "algo" (ou para o instantâneo), o que poderia armazenar a bandeira.

Respondeu 10/12/2008 em 00:09
fonte usuário

votos
4

Em C / C ++ normalmente você pode manter o fato de que doMyFunction () é chamado apenas uma vez encapsulado usando uma variável estática assim:

void doMyFunction() {
     // gets called only once.
     // side effects go here.
}

void functionThatGetsCalledALot() {
    static bool called = false;
    if (!called) {
        doMyFunction();
        called = true;
    }
    // do more stuff
}

Isso evita o uso de globals, mas tem o mesmo efeito, ea var estático é declarado exatamente onde ele é relevante, por isso é claro o que está acontecendo. Note que este não é thread-safe, então você vai precisar de um bloqueio se você tiver threads.

Respondeu 10/12/2008 em 00:09
fonte usuário

votos
7

Quando você chamar uma função que deve fazer o que você espera que ele faça com os argumentos que lhe dão. Se você chamar uma função duas vezes em exatamente da mesma maneira que você deve esperar que a função de dar-lhe os mesmos resultados ou fazer a mesma coisa.

É provavelmente melhor para mover essa dependência chamada uma vez para a lógica que chama sua função muitas vezes. Se você só precisa chamar a função uma vez só então chamá-lo de uma vez. Alternativamente, passar diferentes argumentos para a função para indicar que você está fazendo algo diferente.

Respondeu 10/12/2008 em 00:17
fonte usuário

votos
0

Em Perl 5.10 ou posterior, você usaria uma statevariável.

use 5.010;

sub test{
  state $once = 1;

  if( $once ){
    $once = undef;
    say 'first';
  } else {
    say 'not first';
  }
}

test for 1..5;

saídas

primeiro
não primeiro
não primeiro
não primeiro
não primeiro
Respondeu 10/12/2008 em 21:01
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more