2017-05-03 98 views
-1

我有一個項目在學校做一個WPF項目,使加密和解密的輸入文本。我希望應用程序具有響應能力,但始終會凍結。C#同步wpf

我想使用TPL並使用TaskScheduler.FromCurrentSynchronizationContext(),但它不起作用。我不想使用Dispatcher或其他什麼特定於WPF的東西。

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

如果您的加密函數凍結應用程序,則可能需要使用[多線程](https://www.tutorialspoint.com/csharp/csharp_multithreading.htm),以便您可以同時運行UI更新。 –

+0

如果你想要你的應用程序是'響應',那麼首先你需要消除連續運行的2個循環!如果沒有其他措施將你的絃樂利用率減半,肯定會有所幫助。其次,由於你的加密是內聯的,你可能會試圖使用TPL。 KISS - 保持簡單,愚蠢。先做直接加密,然後看看是否需要考慮多線程。 –

回答

0

涉及加密的重構方法。請參閱下面的代碼相關評論:

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; 
    } 

一些評論涉及到上面的代碼。 代碼工作方式如下:

  1. 從文本框中逐行讀取行。
  2. 進程每一行逐個 (在線程池上下文),以便在線路都在輸入
  3. 當完成了所有行的處理中,加密的結果添加到 輸出文本框

的在以前的代碼中的問題是UI線程訪問過於頻繁,這導致在處理期間UI凍結。

現在處理將在後臺線程中進行並僅在所有處理完成時纔在UI上呈現。

此外,我建議您添加某種指標來通知用戶輸入正在處理:進度條或其他內容。

+0

這是一個按鈕上的點擊事件,當我按下按鈕時,我想從文本框中加密我的文本,並且我想在另一個文本框上顯示。我試圖一次性加密TextBox中的所有文本,並且在加密發生時它不會凍結,但是在顯示文本後我的應用程序完全凍結。我需要在加密之前逐行取出TextBox中的所有文本。 – Rubyen

+0

看來問題可能與問題中的代碼無關。如果它不安全或不適合,請將代碼壓縮併發送給我。我會看看它。 – Alex

+0

[這裏](https://ufile.io/8qtln)是項目 – Rubyen