我在学校有一个项目来制作一个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 :(得分: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;
}
有关上述代码的一些评论。 代码以下列方式工作:
以前代码中的问题是UI线程访问过于频繁,这导致UI在处理过程中冻结。
现在处理进入后台线程,并且仅在所有处理完成时才在UI上呈现。
此外,我建议您添加某种指示器以通知用户输入正在处理:进度条或其他内容。