C#同步wpf

时间:2017-05-03 18:46:15

标签: c# wpf task-parallel-library

我在学校有一个项目来制作一个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);               
}

1 个答案:

答案 0 :(得分: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. 处理完所有行后,将加密结果添加到 输出文本框
  4. 以前代码中的问题是UI线程访问过于频繁,这导致UI在处理过程中冻结。

    现在处理进入后台线程,并且仅在所有处理完成时才在UI上呈现。

    此外,我建议您添加某种指示器以通知用户输入正在处理:进度条或其他内容。