Application.DoEvents();
8 Réponses :
Le .isbusy n'indique que si le travailleur d'arrière-plan est en réalité une opération. Il sera occupé jusqu'à ce que "quelque chose" soit terminé. Il semble que "quelque chose" ne finisse pas, en gardant vos collectivités occupées. P>
Cela aiderait donc si vous pouviez expliquer ce que "quelque chose" est, et peut-être combien de temps il faut pour effectuer "quelque chose" sur le fil principal. P>
Je vous suggère de changer votre code pour gérer l'événement PULDWORKERCOMPLETED CODE> Pour obtenir des notifications lorsque votre code> Backworker code> S est terminé avec leur travail. Il existe un exemple de Comment utiliser le travailleur d'arrière-plan code> dans la documentation officielle . p>
J'ai eu ce même problème tout en utilisant des travailleurs de fond et je suis devenu la conclusion que si vous utilisez le sommeil () dans une boucle, il restera bloqué. Vous pouvez utiliser l'événement d'exécution pondilé et définir un drapeau booléen pour indiquer lorsque chaque travailleur est terminé. P>
ou si vous voulez abandonner le fil, que vous puissiez regarder à l'aide de threads au lieu des travailleurs de fond. Cependant, vous perdez la facilité d'utilisation en ce qui concerne les événements que le travailleur de fond fournit. P>
Urrgh - Oui, ne soyez pas paresseux - dormez () juste mord moi aussi
Votre boucle cause une impasse, le BGWS ne peut pas terminer. Le problème est l'événement déroulantPomptez-vous, il est soulevé sur le fil de l'interface utilisateur. Ce bit de BGW Magic nécessite que le fil de l'interface utilisateur soit inactif, il doit s'agenouiller de sa boucle de message. Le problème est que le thread de l'interface utilisateur n'est pas inactif et ce n'est pas pompant des messages, il est bloqué dans la boucle. Ainsi, le gestionnaire d'événements ne peut pas courir et Isbusy reste vrai. P>
Vous aurez besoin de le faire différemment. Tirez parti de l'événement RunworkerComplet pour exécuter le code que vous exécuteriez normalement après cela pour la boucle. Résistez à toute la tentation d'appeler Application.Deevents () à l'intérieur de la boucle. P>
C'est presque comme un éternel pour, et rien ne fonctionne après. Je vérifie les disponibilités de site Web dans une matrice (à l'aide de l'indice de For), il n'ya donc aucun moyen de simplement "continuer" dans le menuiserieCommandé. Si vous avez des sugestions, veuillez éditer votre réponse .. je suis désemparé :(
Et ça complète. Je l'ai suivi avec le débogueur et il arrive à la "}" à un point donné quand il y a eu un peu de sommeil (0001) qui n'est pas autant qu'au temps d'exécution, car il y a du temps entre l'étape de l'étape, donc je Dormez (0001) environ 20 fois ... puis il se déroule à nouveau, va jusqu'au '}', mais même après la dernière "}" de la Dowork, le BGW ne changera pas l'isbusy en faux.
Non, ce n'est pas complet avant que l'événement pompadéd est terminé. Ce qui se produit après la fin du gestionnaire d'événements de Dowork. Le gestionnaire RWC est le problème, il ne peut pas fonctionner car votre fil d'interface utilisateur est bloqué dans une boucle. Supprimer le gestionnaire serait une solution rapide.
Vous m'avez dit de résister à la mise en place de l'application.Deevents () dans la boucle ... pourquoi?
Parce que votre programme se bloque et brûlera lorsque l'utilisateur ferme le formulaire pendant que votre boucle est en cours d'exécution. Travaillez autour de cela en définissant la propriété Activer le formulaire à FALSE avant d'entrer dans la boucle.
Votre fil principal doit pomper les messages Windows (appeler l'application. Doevents dans votre boucle tandis que dans votre boucle ou mieux en utilisant un système.windows.forms.ticer au lieu d'une boucle). P>
Si vous ne pumpez pas les messages Windows, les notifications «complétées» de votre travailleur de référence ne seront pas traitées, le statut restera occupé. P>
Le problème est que tout ce que vous faites dans Voici un exemple de travail, qui sélectionne le prochain ouvrier libre: P> travailleur.runworkerasync () code> ne finit jamais. Peut-être qu'il y a une boucle sans fin ou quelque chose du genre défini dans votre événement
dowork code>.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
private static List<MyWorker> _Workers;
static void Main(string[] args)
{
_Workers = new List<MyWorker>();
for (int i = 0; i < 5; i++)
{
_Workers.Add(CreateDefaultWorker(i));
}
StartJobs(20000);
Console.ReadKey();
}
private static void StartJobs(int runtime)
{
Random rand = new Random();
DateTime startTime = DateTime.Now;
while (DateTime.Now - startTime < TimeSpan.FromMilliseconds(runtime))
{
var freeWorker = GetFreeWorker();
if (freeWorker != null)
{
freeWorker.Worker.RunWorkerAsync(new Action(() => DoSomething(freeWorker.Index, rand.Next(500, 2000))));
}
else
{
Console.WriteLine("No free worker available!");
Console.WriteLine("Waiting for free one...");
WaitForFreeOne();
}
}
}
private static MyWorker GetFreeWorker()
{
foreach (var worker in _Workers)
{
if (!worker.Worker.IsBusy)
return worker;
}
return null;
}
private static void WaitForFreeOne()
{
while (true)
{
foreach (var worker in _Workers)
{
if (!worker.Worker.IsBusy)
return;
}
Thread.Sleep(1);
}
}
private static MyWorker CreateDefaultWorker(int index)
{
var worker = new MyWorker(index);
worker.Worker.DoWork += (sender, e) => ((Action)e.Argument).Invoke();
worker.Worker.RunWorkerCompleted += (sender, e) => Console.WriteLine("Job finished in worker " + worker.Index);
return worker;
}
static void DoSomething(int index, int timeout)
{
Console.WriteLine("Worker {1} starts to work for {0} ms", timeout, index);
Thread.Sleep(timeout);
}
}
public class MyWorker
{
public int Index { get; private set; }
public BackgroundWorker Worker { get; private set; }
public MyWorker(int index)
{
Index = index;
Worker = new BackgroundWorker();
}
}
}
J'ai eu un problème similaire et ce que j'ai fait pour résoudre le problème était de mettre la fonction principale avec un essayer ... et enfin ... Code> Déclaration. P>
Une solution de travail pour votre problème est donnée dans l'exemple ci-dessous. Comme Hans Passant a expliqué que votre code est exécuté dans le travailleur d'arrière-plan, mais le tranchantCommandé de chaque thread n'est évalué que dans le fil de l'interface utilisateur. Pour ce faire, vous pouvez en faire votre demande dans la file d'attente d'UIS de threads, le threadpool. De cette façon, l'interface utilisateur d'interface utilisateur est d'évaluer le pancarboratchcleteDevente et après cela retourne à votre code.
for (int i = 0; i < 999999; ++i) { System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback((x) => { while (backgroundWorker1.IsBusy && backgroundWorker2.IsBusy) { System.Threading.Thread.Sleep(0); } // Code that is beging executed after all threads have ended. myCode(); })); if (!backgroundWorker1.IsBusy) { backgroundWorker1.RunWorkerAsync(); } else if (!backgroundWorker2.IsBusy) { backgroundWorker2.RunWorkerAsync(); } }
La descente sans donner la raison n'est ni utile ni gentille. Cette réponse est une réponse valide à la question posée et montre comment sortir de l'impasse en utilisant autant de code de l'intervenant que possible.
Le moyen le plus simple de déterminer si le travail est terminé est de supprimer un point d'arrêt sur l'événement du pompadeur d'exécutation et de laisser exécuter le programme. Si vous frappez le point d'arrêt, le travailleur d'arrière-plan a terminé le travail.