Bienvenue à SO!
Quelques petites choses me viennent immédiatement à l'esprit.
Tout d'abord, éliminons le problème de l'événement. Vous avez la bonne approche - vous avez besoin d'un événement et d'une méthode pour l'appeler, mais cette méthode doit vérifier si l'événement est null
.
En gros, faites ceci:
public event EventHandler OnConsoleUpdate;
public void ConsoleUpdate()
{
OnConsoleUpdate?.Invoke(this, EventArgs.Empty);
}
Le fait ci-dessus l'utilisation de ?
, un opérateur état nul. Vous pouvez en savoir plus à ce sujet on this MSDN page.
Deuxième chose ... on ne sait pas vraiment ce que votre travailleur d'arrière-plan est réellement. On dirait que c'est une sorte de cours personnalisé que vous avez créé? La raison pour laquelle c'est important est que .NET a en fait une classe BackgroundWorker
utilisée pour les opérations en cours ... bien, en arrière-plan. Il a également un événement OnProgressChanged
auquel vous pouvez vous connecter et qui peut être utilisé pour mettre à jour l'interface utilisateur (n'oubliez pas de définir la propriété WorkerReportsProgress
sur true
). Et pour utiliser le BackgroundWorker
mentionné ci-dessus, vous ne devriez pas avoir besoin de créer vos propres événements.
Voici comment vous pouvez utiliser la norme.NET BackgroundWorker
:
System.ComponentModel.BackgroundWorker worker = new System.ComponentModel.BackgroundWorker();
void StartBackgroundTask()
{
worker.DoWork += worker_DoWork;
//if it's possible to display progress, use this
worker.WorkerReportsProgress = true;
worker.ProgressChanged += worker_ProgressChanged;
//what to do when the method finishes?
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
//start!
worker.RunWorkerAsync();
}
void worker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
{
//perform any "finalization" operations, like re-enable disabled buttons
//display the result using the data in e.Result
//this code will be running in the UI thread
}
//example of a container class to pass more data in the ReportProgress event
public class ProgressData
{
public string OperationDescription { get; set; }
public int CurrentResult { get; set; }
//feel free to add more stuff here
}
void worker_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
{
//display the progress using e.ProgressPercentage or e.UserState
//this code will be running in the UI thread
//UserState can be ANYTHING:
//var data = (ProgressData)e.UserState;
}
void worker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
//this code will NOT be running in the UI thread!
//you should NOT call the UI thread from this method
int result = 1;
//perform calculations
for (var i = 1; i <= 10; i++)
{
worker.ReportProgress(i, new ProgressData(){ OperationDescription = "CustomState passed as second, optional parameter", CurrentResult = result });
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(5));
result *= i;
}
e.Result = result;
}
Maintenant, la chose au sujet de la classe BackgroundWorker
est qu'il est assez vieux, et avec les versions .NET actuelles, vous pouvez utiliser les async/await
mots-clés pour gérer facilement les opérations d'arrière-plan et les mises à jour l'interface utilisateur, mais cela est probablement aller en dehors des limites de cette question. Cela dit, l'existence de async/await
n'invalide pas l'utilisation de BackgroundWorker
ce qui est assez simple dans son utilisation.
Il y a une chose plus inquiétante dans votre code.
public void BackgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
StandardTasks task = new StandardTasks(); //<- you create a task
Helper helper = new Helper(); // <- you create a helper
helper.OnConsoleUpdate += Processchange; // <- you hook up to the helper event
task.DoSomeStuffHere(); // <- you do stuff with the task... but the task doesn't know about your helper above! Does `StandardTasks` use `Helper`? If so, how?
}
Prenez note que les événements, à moins d'être static
, ne sont pas globaux. Ainsi, se connecter à un événement dans une instance d'une classe ne provoquera pas une autre instance de cette classe à "déclencher" cet événement. Il semble un moyen de résoudre vos problèmes serait de faire de la prendre classe StandardTasks
Helper
comme l'un des paramètres du constructeur, de sorte que le code ressemblerait à ceci:
Helper helper = new Helper(); // <- you create a helper
helper.OnConsoleUpdate += Processchange; // <- you hook up to the helper class event to actually do something
StandardTasks task = new StandardTasks(helper); //<- you create a task which will use the helper with the hooked up event above
est-il une option pour passer à motif Async base de travail (ROBINET)? Ensuite, vous pouvez simplement démarrer une tâche sur le ThreadPool et lui passer un objet Progress. Si vous voulez coller avec l'arrière-plan, vous devez afficher plus de code pertinent. – Fildor
Où avez-vous démarré cet arrière-plan? Je vois quelque chose comme ça: backgroundWorker1.RunWorkerAsync(); – Arkadiusz
BTW: Avoir une classe "GlobalVar" ... qui a une odeur de code ... – Fildor