7
votes

C # Rappel ASYNC toujours sur le fil de fond ... Aide! (de préférence sans invoquée)

J'écris une classe d'assistance asynchrone très simple pour aller avec mon projet. Le but de la classe est qu'il permet une méthode d'exécution sur un fil d'arrière-plan. Voici le code;

txtOutput.AppendText(e.Result + Environment.NewLine);


1 commentaires

Êtes-vous sur .NET 2.0, 3.5, 4.0? Et créez-vous une application WinForms, WPF, Silverlight?


5 Réponses :


0
votes

Vous devez appeler votre événement sur le fil de l'interface utilisateur,

Winforms

form1.begininvoke (...);

wpf

Dispatcher.begininvoke (...);


3 commentaires

Suggérez-vous cela? onOperationComplete.begininvoke


isynchronizeInvoke est une interface obsolète et ne doit pas être utilisée.


@Jon, non, il vous suggère d'appeler la méthode BegweinVoke ou InvoKe trouvée sur un contrôle visuel. De cette façon, vous fermerez l'appel sur le fil de l'interface graphique, et cela vous permettra de manipuler l'état de l'interface graphique. Délégué.begininvoke et Control.begininvoke n'est pas la même chose.



0
votes

Utilisez la classe Travailleur d'arrière-plan, vous le réprimande essentiellement ici.


0 commentaires

5
votes

Utiliser la classe des travailleurs en arrière-plan. Cela fait essentiellement la même chose que vous voulez.

        private BackgroundWorker _worker;

    public Form1()
    {
        InitializeComponent();
        _worker = new BackgroundWorker();
        _worker.DoWork += Worker_DoWork;
        _worker.RunWorkerCompleted += Work_Completed;
    }

    private void Work_Completed(object sender, RunWorkerCompletedEventArgs e)
    {
        txtOutput.Text = e.Result.ToString();
    }

    private void Worker_DoWork(object sender, DoWorkEventArgs e)
    {
        e.Result = "Text received from long runing operation";
    }


3 commentaires

Vous pouvez également signaler le paramètre de progression: _worker.workerrportsprogress = true; // et _worker.ProgressSchangned + = progress_changed;


J'ai un peu oublié ... Pour exécuter le travailleur, vous devez appeler la méthode _worker.RunworkerAsync ().


Je suis allé pour le travail d'arrière-plan à la fin, mais je vous ai tout compris et mis dans des événements personnalisés afin que personne ne sache jamais. En supposant qu'ils ne regardent pas la source bien sûr. (Le fait que le projet est open source est une légère faille, mais oh bien)



0
votes

Sauf si vous construisez votre classe d'aide pour effectuer le changement de contexte interne, vous aurez toujours besoin d'appeler dans le gestionnaire d'événements car dans votre code ci-dessus, vous soulevez l'événement sur le fil non-UI.

Pour ce faire votre aide doit savoir comment revenir sur le fil de l'interface utilisateur. Vous pourriez passer un isynchronizeInvoke à l'aide de l'aide et ensuite Utilisez-le lorsque vous avez terminé. Somwout comme: xxx

Contrôle implémente de la classe isynchronizeinvoke afin que vous puissiez transmettre le ceci Pointeur du formulaire ou Contrôle qui appelle l'assistant et a le délégué du gestionnaire d'événements,


1 commentaires

isynchronizeInvoke est une interface obsolète et ne doit pas être utilisée.



3
votes

Je recommande d'utiliser la liste code> Classe Code> Classe plutôt que Backworker CODE>, mais serait plus grandement supérieur à contrôler.invoke code> ou Dispatcher.invoke code>.

Exemple : P>

internal class AsyncHelper<T>
{ 
  private readonly Stopwatch timer = new Stopwatch(); 
  private readonly TaskScheduler ui;

  // This should be called from a UI thread.
  internal AsyncHelper()
  {
    this.ui = TaskScheduler.FromCurrentSynchronizationContext();
  }

  internal event DownloadCompleteHandler OnOperationComplete; 

  internal Task Start(Func<T> func)
  { 
    timer.Start();
    Task.Factory.StartNew(func).ContinueWith(this.Done, this.ui);
  }

  private void Done(Task<T> task) 
  {
    timer.Stop();
    if (task.Exception != null)
    {
      // handle error condition
    }
    else
    {
      InvokeCompleteEventArgs(task.Result); 
    }
  } 

  private void InvokeCompleteEventArgs(T result) 
  { 
    var args = new EventArgs(result, null, AsyncMethod.GetEventByClass, timer.Elapsed); 
    if (OnOperationComplete != null) OnOperationComplete(null, args); 
  } 

  internal delegate void DownloadCompleteHandler(object sender, EventArgs e); 
} 


7 commentaires

Est-ce que vous l'avez vu? Mes "trois pages" incluent une solution complète avec l'interface utilisateur, la prise en charge d'une annulation, une correction correcte des erreurs d'erreur, etc. Aucune de laquelle votre solution inclut.


J'aime ça, mais je ne sais pas comment mettre en œuvre, pourriez-vous donner l'exemple d'utilisation?


J'ai mis à jour l'exemple similaire au code de votre question, montrant comment il serait utilisé dans cette situation.


hmm il jette toujours une erreur; Fonctionnement transversal non valide: Contrôle 'TxtoutOutput' accédé à partir d'un fil autre que le thread qui a été créé.


Avez-vous construit asynchelper sur le fil d'interface utilisateur, comme indiqué le commentaire?


désolé j'ai dû manquer cela. La classe d'assistance provient d'une autre classe instanciée du fil de l'interface utilisateur. cela compte-t-il.


Oui, tant que le fil de l'interface utilisateur a déjà créé (et montré) un contrôle.