web-dev-qa-db-fra.com

Comment s'assurer que les finitions de méthode fonctionnent avant d'être exécutées à nouveau

Je suis nouveau et j'essaie de comprendre quelque chose. J'ai un programme simple qui exécute une méthode soit lorsqu'un événement se produit ou lorsque ma minuterie tick. Permet simplement de dire que la méthode prend 5 secondes à compléter. Au cours de ces 5 secondes, un événement pourrait arriver. Qu'aurais-je utiliser/faire pour vous assurer que ma méthode n'est pas appelée alors que c'est déjà en cours d'exécution.

Ou est-ce quelque chose que je n'aurais pas à vous soucier d'un programme simple, car il ne serait pas exécuté avant que la méthode soit faite de toute façon?

Un petit fond et exemple. J'utilise System.Windows.Forms.Timer, je n'utilise aucun fil ou quoi que ce soit, et je viens d'avoir une simple application de formulaire Windows avec une minuterie, une méthode pour faire des trucs et deux gestionnaires d'événements.

Program{
  public Program(){
    DoSomething();
    Event.EventHappened += HandleEvent;
  }
  void DoSomething(){
    MyTimerVariable.Stop();
    InitMyTimer();
    //Just do something check network, access db write line, something
    //that in this example takes 5 secs for example purposes
    MyTimerVariable.Start();
  }
  void HandleEvent(){
    DoSomething();
  }
  void InitMyTimer(){
    // Create Timer, and add Timer tick event
  }
  void TimerTickedEvent(){
    DoSomething();
  }
}

J'ai laissé quelques choses sur ce programme, mais essayait simplement de montrer à quel point c'est simple. Je pensais juste à la rendre plus efficace de sorte que dire au milieu de la pratique "Dosomethant ()" Un événement est déclenché, je ne voudrais pas que deux "" de la méthode "de Dosomethant ().

2
RWhiten

Comme cela utilise un système.windows.forms.Timer au lieu de System.threading.Timer, l'événement sera exécuté sur le thread de l'interface utilisateur et ne sera donc pas exécuté hors de séquence.

Si vous utilisiez cependant, créez-la simplement une méthode private object lockObject = new object(); [Fonction ()] DoSomething() [Fonction (Fonction ()] _, vous garantissez la même chose que le corps de dosomething n'est pas exécuté tant qu'il n'en est pas terminé.

5
Stephen

Je suis d'accord avec @theficus pour le style de code.

Cependant, la mise en œuvre en détail.

J'ai eu de nombreux cas où plus d'un thread est entré dans un bloc de code utilisant uniquement son type de vérification de l'implémentation booléenne. Raising toutes sortes de ravages et de la confusion, puisque le supposé impossible réellement passé. Tout type d'algorithme de verrouillage de fil qui ne fonctionne que la plupart du temps, mais pas à chaque fois est à mon humble avis inutile.

Le Interlocked. * API pour ce cas d'utilisation est tout aussi simple que le booléenne contrôle la mise en œuvre et rend absolument sûr qu'un seul thread entre dans le bloc de code et tous les autres continuent.

private int isBusy = 0;

private void MyWorkerMethod()
{
  if(System.Threading.Interlocked.CompareExchange(ref this.isBusy, 1, 0) == 1)
  {
    return;
  }

  try
  {
    // do stuff
  }
  finally
  {
    this.isBusy = 0;
  }
}
3
TiltonJH

Si l'intention réelle est de vous assurer que vous n'aurez pas de méthodes de travail multiples travaillant en même temps, la manière la plus simple serait une chose comme ceci:

bool isBusy = false;
void MyWorkerMethod()
{
  if(isBusy == true)
  {
    return;
  }

  try
  {
    isBusy = true;
    // do stuff
  }
  finally
  {
    isBusy = false;
  }
}

De cette façon, chaque fois que la minuterie ticks, il exécute toujours votre méthode, mais votre méthode quittera immédiatement si elle est au milieu de travailler avec un minimum de fiches. Si vous utilisez le verrouillage, vous obtiendrez de la conflit de fil en attendant que la serrure soit libérée que je suppose que ce que vous voulez.

Si vous êtes super paranoïaque, vous pourriez également regarder dans les verrouillés. * API pour vous assurer au-delà d'une ombre d'un doute sur le fait que vous n'avez jamais votre travailleur qui fonctionne plus d'une fois, mais que cela peut être surchargé ici.

2
theficus