J'essaie de faire un système de type plugin. J'ai fait quelque chose dans le passé où tous les plugins s'exécutent dans le thread principal, ce qui entraîne des problèmes si les plugins prennent beaucoup de temps. J'ai donc pensé que j'exécuterais les méthodes appropriées dans chaque plugin en utilisant les tâches.Tâche (ou thread) nécessite attendre ou rejoindre pour travailler
J'ai un programme principal, qui charge chaque plugin en utilisant Assembly.LoadFile, puis réagit aux commandes que l'utilisateur tape. Si l'une de ces commandes est gérée par un plugin (les plugins signalent quelles commandes ils gèrent, le programme principal demande quand il les charge), mon programme démarrera une méthode dans le plugin dans sa propre tâche. Chaque plugin implémente également un événement utilisé lorsqu'il a des données à envoyer au programme principal pour la sortie. Le programme principal attache un gestionnaire à cet événement lorsqu'il charge chaque plugin.
La méthode ProcessCommand du plugin effectue le travail nécessaire, déclenche l'événement OnOutput, puis se termine.
Ceci est un plugin très simple:
public override void ProcessCommand(PluginCommand Command, PluginParameters Parameters, PluginContext Context)
{
OnOutputGenerated(this,"Hello from Plugin A");
}
Cela a bien fonctionné avec le premier plug-in que j'ai fait. J'ai donc créé un autre, en utilisant exactement le même code, en changeant juste "Bonjour du Plugin A" à "Bonjour du Plugin B."
Le plugin A fonctionne toujours. Si j'émets la commande appropriée dans le programme principal, il s'exécute et dit Bonjour de Plugin A. Great.
Le problème est le suivant: Le plugin B s'exécute peut-être une fois toutes les 30 tentatives. Je l'ai découvert, cependant, que si appeler le plug-in de la manière suivante, il fonctionne à chaque fois:
Task t = Task.Factory.StartNew(() => Plugin.ProcessCommand(cmd, Params, Context));
t.Wait(100);
Y at-il une raison technique pourrait aider? J'ai lu à peu près tout de http://www.albahari.com/threading/ essayant de comprendre les choses, mais je n'ai pas eu de chance.
Il est à noter que j'ai également fait cela avec des threads, avec le même problème.
Thread t = new Thread(() => Plugin.ProcessCommand(cmd, Params, Context));
t.Start();
Ajout:
t.Join(100);
"fixe" il.
Mise à jour
J'ai tout simplifié. J'ai fait un nouveau projet, qui supprime tout le code sans rapport avec les bugs.
foreach (string File in Directory.GetFiles(PluginDir, "*.dll")) {
try {
IPlugin Plugin = PluginManager.LoadPlugin(File);
Plugin.OnOutputGenerated += new PluginOutputEvent(Plugin_OnOutputGenerated);
} catch (Exception ex) {
}
}
// main loop
string Line = Console.ReadLine();
foreach (IPlugin Plugin in PluginManager.LoadedPlugins) {
foreach (PluginCommand cmd in Plugin.GetCommands()) {
if (cmd.Command.Equals(Line, StringComparison.InvariantCultureIgnoreCase)) {
PluginParameters Params = cmd.TryParseParameters(ParamString);
Task t = Task.Factory.StartNew(() => Plugin.ProcessCommand(cmd, Params, Context));
}
}
}
// output handler
static void Plugin_OnOutputGenerated(IPlugin Plugin, string OutputString) {
Console.WriteLine("Output: " + OutputString);
}
Le problème principal a changé. Auparavant, l'un des plugins ne fonctionnait pas la plupart du temps. Imaginez deux plugins.
Plugin A
* A une commande: Commanda
* Commande déclenche l'événement OnOutputGenerated avec la chaîne "Bonjour du plugin A"
Plugin B
* A une commande: CommandB
* La commande déclenche l'événement OnOutputGenerated avec la chaîne "Hello from Plugin B"
Si je lance ce nouveau projet, j'ai fait, et émettez la commande "CommandA", il retournera "Bonjour du Plugin B". Cela continue jusqu'à ce que j'émette réellement "CommandB". Une fois que j'ai fait cela, il affiche "Hello from Plugin B" (comme il se doit). Si je répète "CommandA", il renvoie "Hello from Plugin A" (comme il aurait dû l'être à l'origine).
Si j'ajoute
t.Wait(100);
il est fixe. Cela semble toujours lié à la tâche, mais je n'arrive pas à expliquer comment. Il semblerait que ma logique soit bonne sinon. Je ne vois pas comment il exécuterait le Plugin B lorsqu'il devrait exécuter le Plugin A, ou vice-versa.
Se pourrait-il que votre variable de tâche t soit hors de portée avant qu'elle se termine? –