2017-05-03 46 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