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?
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
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);
}
J'examinerais la file d'attente des tâches qui doivent être faites. Vous bénéficiez des avantages suivants;
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.
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.