web-dev-qa-db-fra.com

Ce BackgroundWorker est actuellement occupé et ne peut pas exécuter plusieurs tâches simultanément

J'obtiens cette erreur si je clique sur un bouton qui démarre le backgroundworker deux fois.

This BackgroundWorker is currently busy and cannot run multiple tasks concurrently

Comment puis-je éviter ça?

49
Jade M

Simple: ne démarrez pas BackgroundWorker deux fois.

Vous pouvez vérifier s'il est déjà en cours d'exécution en utilisant la propriété IsBusy, il vous suffit donc de modifier ce code:

worker.RunWorkerAsync();

pour ça:

if( !worker.IsBusy )
    worker.RunWorkerAsync();
else
    MessageBox.Show("Can't run the worker twice!");

Mise à jour:

Si vous devez réellement lancer plusieurs tâches d'arrière-plan en même temps, vous pouvez simplement créer plusieurs objets BackgroundWorker

92
Orion Edwards

Créez un nouvel objet BackgroundWorker pour chaque opération que vous souhaitez effectuer. C'est-à-dire plutôt que:

BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
for (int i; i < max; i++) {
   worker.RunWorkerAsync(i);
}

Essaye ça:

for (int i; i < max; i++) {
   BackgroundWorker worker = new BackgroundWorker();
   worker.DoWork += new DoWorkEventHandler(worker_DoWork);
   worker.RunWorkerAsync(i);
}
53
Justin R.

J'examinerais la file d'attente des tâches qui doivent être faites. Vous bénéficiez des avantages suivants;

  • Vous n'avez pas à gérer les problèmes de tâches en arrière-plan ne pouvant pas démarrer en raison de quelque chose d'autre déjà en cours d'exécution
  • Vous n'avez pas à vous soucier d'utiliser trop de threads, en créant un nouvel arrière-plan travaillé pour chaque tâche.
  • Enfin, la file d'attente pourrait vous permettre de vous assurer que les tâches en arrière-plan s'exécutent dans le même ordre qu'elles ont été créées/demandées.

Voici un exemple d'implémentation: http://thevalerios.net/matt/2008/05/a-queued-backgroundworker . Je ne sais pas si l'implémentation dans threadsafe, et je mettrai à jour ma réponse une fois que je découvrirai mon problème de verrouillage actuel dans une implémentation avec laquelle je travaille.

7
Thies

Bien que ce ne soit pas le cas initialement demandé par l'OP, cela peut également se produire en raison d'une condition de concurrence (ce qui m'est arrivé maintenant et j'ai cherché une réponse) si vous utilisez un travailleur en arrière-plan dans une sorte de modèle producteur-consommateur.

Exemple:

if (BckgrndWrkr == null)
{
    BckgrndWrkr = new BackgroundWorker(); 
    BckgrndWrkr.DoWork += DoWorkMethod;
    BckgrndWrkr.RunWorkerAsync();     
}
else if (!BckgrndWrkr.IsBusy)
{
    BckgrndWrkr.RunWorkerAsync();
}

Dans ce cas, il y a une condition de concurrence: la première instance instancie un nouveau travailleur en arrière-plan, la deuxième instance atteint le else if et démarre le travail en arrière-plan, avant que la 1ère instance n'atteigne RunWorkerAsync du bloc if, et quand il le fait, il renvoie l'erreur.

Cela peut être évité en ajoutant un verrou à toute la section if + if else.

1
David Refaeli