2017-05-03 2 views
-1

Ich habe ein Projekt in der Schule, um ein WPF-Projekt zu machen, die Verschlüsselung und Entschlüsselung eines Eingabetextes macht. Ich möchte, dass die Anwendung reagiert, aber immer einfriert.C# synchronisieren wpf

Ich möchte TPL verwenden und ich benutze TaskScheduler.FromCurrentSynchronizationContext(), aber es funktioniert nicht. Ich möchte nicht Dispatcher oder etwas anderes verwenden, was nur für WPF spezifisch ist.

tokenSource = new CancellationTokenSource(); 
int lineCount = textBoxInput.LineCount; 
string encryptTextInput = ""; 

List<string> listText = new List<string>(); 
List<Task> listTask = new List<Task>(); 

var ui = TaskScheduler.FromCurrentSynchronizationContext(); 

for (int cnt = 0; cnt < lineCount; cnt++) 
{ 
    encryptTextInput = textBoxInput.GetLineText(cnt); 
    listText.Add(encryptTextInput); 
} 

for (int cnt = 0; cnt < lineCount; cnt++) 
{ 
    int line = cnt; 

    var myTask = Task.Factory.StartNew(result => 
    { 
     return EncryptDecrypt.Encrypt(listText[line]); 
    }, tokenSource.Token); 
    listTask.Add(myTask); 

    var display = myTask.ContinueWith(resultTask => 
    textBoxOutput.Text += myTask.Result.ToString(), CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion, ui); 

    var displayCancel = myTask.ContinueWith(resultTask => 
    textBoxOutput.Text += myTask.Result.ToString(), CancellationToken.None, TaskContinuationOptions.OnlyOnCanceled, ui);    
} 
+0

Wenn Ihre Verschlüsselungsfunktion die Anwendung einfriert, müssen Sie möglicherweise [Multi-Threading] (https://www.tutorialspoint.com/csharp/csharp_multithreading.htm) verwenden, damit Sie die UI-Aktualisierungen gleichzeitig ausführen können . –

+0

Wenn Sie möchten, dass Ihre Anwendung "reaktionsfähig" ist, dann müssen Sie zuerst zwei Schleifen hintereinander eliminieren! Wenn nichts anderes die String-Nutzung halbiert, wird das sicher helfen. Zweitens, da Ihre Verschlüsselung inline ist, übertreiben Sie möglicherweise die Verwendung von TPL. KISS - halte es einfach, dumm. Tun Sie einfach zuerst die direkte Verschlüsselung, dann sehen Sie Wenn Sie Multithreading in Betracht ziehen müssen. –

Antwort

0

Refaktorierte Methode, die sich auf die Verschlüsselung bezieht. Bitte beachten Sie die Kommentare zum folgenden Code:

private async void buttonEncrypt_Click(object sender, RoutedEventArgs e) 
    { 
     string elapsedTime = string.Empty; 
     Stopwatch stopWatch = new Stopwatch(); 
     stopWatch.Start(); 

     tokenSource = new CancellationTokenSource(); 
     int lineCount = textBoxInput.LineCount; 
     var outputResult = String.Empty; 

     for (int cnt = 0; cnt < lineCount; cnt++) 
     { 
      var lineToProcess = textBoxInput.GetLineText(cnt); 

      //Code inside task will work in thread from thread pool, so the UI thread shouldn't be blocked 
      string result = await Task.Run(() => 
       EncryptDecrypt.Encrypt(lineToProcess), tokenSource.Token); 

      outputResult += result; 

     } 

     //UI thread: when completed update the UI with encrypted text. 
     textBoxOutput.Text = outputResult; 

     stopWatch.Stop(); 
     TimeSpan ts = stopWatch.Elapsed; 
     elapsedTime = String.Format("{0:00}:{1:00}:{2:00}:{3:00}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds/10); 
     time.Content = elapsedTime; 
    } 

Ein paar Kommentare zum obigen Code. Der Code in der folgenden Art und Weise arbeiten:

  1. lesen Zeilen von Text Zeile für Zeile.
  2. verarbeitet jede Zeile nacheinander (in Thread-Pool-Kontext), um die Linien in Eingang
  3. Wenn die Verarbeitung aller abgeschlossenen Linien, um das Ergebnis der Verschlüsselung an die

Die Textbox Ausgang hinzufügen Problem im vorherigen Code war, dass der UI-Thread zu häufig auftrat und dies dazu führte, dass die Benutzeroberfläche während der Verarbeitung einfror.

Die Verarbeitung wird jetzt im Hintergrundthread ausgeführt und nur auf der Benutzeroberfläche gerendert, wenn die gesamte Verarbeitung abgeschlossen ist.

Ich empfehle Ihnen auch, eine Art Indikator hinzuzufügen, um den Benutzer zu informieren, dass die Eingabe verarbeitet wird: Fortschrittsbalken oder etwas anderes.

+0

Es ist ein Klick-Ereignis auf einer Schaltfläche, wenn ich die Schaltfläche Ich möchte meinen Text aus einer TextBox zu verschlüsseln, und ich möchte auf einer anderen TextBox anzeigen. Ich habe versucht, den gesamten Text von TextBox auf einmal zu verschlüsseln, und es hat nicht eingefroren, während die Verschlüsselung stattfand, aber nach dem Anzeigen des Textes meine Anwendung vollständig einfrieren. Ich muss den gesamten Text von TextBox Zeile für Zeile vor der Verschlüsselung nehmen. – Rubyen

+0

Es scheint, dass das Problem nicht mit dem Code in der Frage zusammenhängen könnte. Könnten Sie bitte den Code zippen, wenn er nicht sicher ist oder etwas und senden Sie es mir. Ich werde es mir ansehen. – Alex

+0

[hier] (https://ufile.io/8qtln) ist das Projekt – Rubyen