2017-05-03 6 views
-1

私は入力テキストの暗号化と復号化を行うWPFプロジェクトを作成するプロジェクトを学校で持っています。私は、アプリケーションが応答したいが、それは常にフリーズします。C#synchronize 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を使用しようと思っているかもしれません。キス - それをシンプルに、愚かに保ちなさい。最初にストレート暗号化を行ってから、マルチスレッドを考慮する必要がある場合を参照してください。 –

答えて

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. テキストボックスから行を1行ずつ読み込みます。 (スレッドプールの文脈における)1 によって
  2. プロセス各行いずれかを全ラインの処理が完了すると線が入力
  3. にあるために、 出力テキストボックスに暗号化の結果を追加

以前のコードの問題は、UIスレッドが頻繁にアクセスしていて、処理中にUIがフリーズしてしまうことでした。

処理がバックグラウンドスレッドで実行され、すべての処理が完了したときにのみUIで表示されます。

また、入力が処理中であることをユーザーに知らせるためのインジケータを追加することをお勧めします。進行状況バーなどです。

+0

ボタンのクリックイベントです。ボタンを押したときに、テキストボックスからテキストを暗号化して別のテキストボックスに表示したい場合があります。一度にTextBoxからすべてのテキストを暗号化しようとしましたが、暗号化が行われている間にフリーズしませんでしたが、テキストを表示した後でアプリケーションが完全にフリーズしました。私はTextBoxからすべてのテキストを1行ずつ暗号化する必要があります。 – Rubyen

+0

問題は、問題のコードに関連していない可能性があります。それが安全でないか何かが私にそれを送るなら、あなたはコードを圧縮してください。私はそれを見てみましょう。 – Alex

+0

[こちら](https://ufile.io/8qtln)は – Rubyen