2010-03-06 6 views
1

Nouveau à wpf si nu avec moi.Vous ne pouvez pas obtenir Threading droite sur wpf UI.Can vous aider

Je construis une application de preuve de concept avant de passer à la vraie.

Scénario Je devrais pouvoir arrêter le traitement au milieu.

Barre d'outils 2 boutons "Start" & "Stop"

start de presse de l'utilisateur et traiter une tâche longue marche. L'utilisateur décide à l'improviste d'arrêter la tâche.

Je n'arrive pas à enfiler correctement! Je ne peux pas appuyer sur stop pour attendre la tâche longue, comme si la tâche longue s'exécutait sur le thread de l'interface utilisateur et non sur le thread d'arrière-plan.

Qu'est-ce que je fais mal, pouvez-vous le repérer? Merci pour votre aide

public partial class TestView : UserControl 
{ 

    private readonly BackgroundWorker _worker; 


    public TestView 
    { 
     InitializeComponent(); 
     _worker = new BackgroundWorker(); 
     _worker.RunWorkerCompleted += RunWorkerCompleted; 
     _worker.DoWork+=DoWork; 
     _worker.WorkerReportsProgress = true; 
     _worker.ProgressChanged+=_worker_ProgressChanged; 
     _worker.WorkerSupportsCancellation = true; 
    } 


    static void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     if (e.Cancelled) 
     { 
      MessageBox.Show("The task has been cancelled"); 
     } 
     else if (e.Error != null) 
     { 
      MessageBox.Show("Error. Details: " + e.Error); 
     } 
     else 
     { 
      MessageBox.Show("The task has been completed. Results: " + e.Result); 
     } 
    } 
    private delegate void SimpleDelegate(); 
    void DoWork(object sender, DoWorkEventArgs e) 
    { 
     for (var i = 0; i < 1000000; i++) 
     { 
      _worker.ReportProgress(i, DateTime.Now); 
      // SimpleDelegate simpleDelegate =() => txtResult.AppendText("Test" + System.Environment.NewLine); 

      //Dispatcher.BeginInvoke(DispatcherPriority.Normal, simpleDelegate); 
     } 

     MessageBox.Show("I have done it all"); 
    } 
    private void _worker_ProgressChanged(object sender, ProgressChangedEventArgs e) 
    { 
     DateTime time = Convert.ToDateTime(e.UserState); 
     txtResult.AppendText(time.ToLongTimeString()); 
     txtResult.AppendText(Environment.NewLine); 
    } 

    private void BtnStart_Click(object sender, RoutedEventArgs e) 
    { 
     _worker.RunWorkerAsync(); 
    } 

    private void BtnStop_Click(object sender, RoutedEventArgs e) 
    { 
     _worker.CancelAsync(); 
     MessageBox.Show("Process has been stopped!"); 
    } 
} 

Répondre

3

Vous exécutez une boucle très serrée à l'intérieur de DoWork et continuellement au ProgressUpdates OPPOSABLES AU thread principal. Cela va le rendre léthargique.

Mais le vrai problème est que DoWork doit coopérer à l'annulation:

void DoWork(object sender, DoWorkEventArgs e) 
{  
    for (var i = 0; i < 1000000; i++) 
    { 
     if (_worker.CancelationPending) 
     { 
     e.Cancel = true; 
     break; // or: return to skip the messagebox 
     } 
     _worker.ReportProgress(i, DateTime.Now); 
    } 

    MessageBox.Show("I have done it all"); // remove or make depend on Cancelled 
} 
+0

Salut Merci pour votre réponse. Toujours ne fonctionne pas. En outre, il n'y a pas un e.Cancelled = true. Vous ne savez pas ce que je fais mal. – user9969

+0

Typo, aurait dû être 'e.Cancel = true'. Votre démo fonctionnera mieux si vous mettez un 'System.Threading.Thread.Sleep (10);' dans la boucle for. –

Questions connexes