我有一个UserControl
项目,该项目由TextBox
,Button
和第三方地图控件组成。
我在TextBox
中输入一个命令,点击Button
,然后代码隐藏在Map control
上做了很多工作。用户可以选择读取包含多个命令的文本文件,并逐行执行。
当用户想要取消当前读取文本文件/执行命令时,问题就出现了。他们希望能够在文本框中键入“取消”,点击按钮,然后停止所有执行。 GUI当然在执行命令时被冻结,因此用户不能输入“取消”并单击按钮来停止执行。
解决此问题的正确方法是什么?这是我的用户控件的代码隐藏:
private void RunScript(string[] command)
{
string filePath = command[1];
Task task = Task.Factory.StartNew(() => { ReadFile(ct, filePath);
}
private void ReadFile(CancellationToken token, string filePath)
{
using (var file = File.OpenText(filePath))
{
string line;
while ((line = file.ReadLine()) != null)
{
if (ct.IsCancellationRequested)
{
ct.ThrowIfCancellationRequested();
}
else
{
if (line == string.Empty || line.StartsWith("//"))
continue;
CallCommands(commandParser.StartParse(line));
}
}
}
tokenSource.Dispose();
}
private void CancelScript()
{
tokenSource.Cancel();
}
private void CallCommands(string command)
{
//do stuff to the Map control. ex:
Map.Refresh(); //problem here
}
因此用户键入Run,点击按钮,它会启动if / else语句的第一个块。我不希望文本框和按钮在执行时被阻止,并希望用户能够发送“取消”以便它停止运行部分。
编辑:更新了我的代码。我在Map.fresh()上遇到问题;它没有执行,只是说“线程已经退出代码0”。我猜这是因为它是UI线程的一部分。我是否必须在使用Map.Refresh()?
的每个方法上使用某种调用答案 0 :(得分:1)
如果您不希望在后台执行操作时阻止UI,则您必须异步执行操作。您可以使用非常简单易用的CancellationToken
,并且可以使用where
取消背景操作。
阅读本文:https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/task-cancellation