【发布时间】:2020-08-09 09:39:21
【问题描述】:
我在 WinForms 中有一个从文本文件导入的按钮。一旦开始导入,它将按钮的文本更改为Processing... 并实例化一个 CancellationToken,如果用户请求,它应该取消操作。如果在导入过程中再次按下按钮,它应该会激活任务取消。
有很多方法可以做到这一点,我无法决定使用哪一种。最干净的方法是什么?
private CancellationTokenSource _cts;
private List<string> _list = new List<string>();
private async void Button_Click(object sender, EventArgs e)
{
if (button.Text == "Processing...")
{
if (_cts != null)
{
_cts.Cancel();
_cts.Dispose();
}
}
else
{
using var dialog = new OpenFileDialog
{
Filter = "All Files (*.*)|*.*"
};
if (dialog.ShowDialog() == DialogResult.OK)
{
button.Text = "Processing...";
_cts = new CancellationTokenSource();
var fileStream = dialog.OpenFile();
using var reader = new StreamReader(fileStream);
try
{
int count = 0;
while (!reader.EndOfStream)
{
var line = await reader.ReadLineAsync().WithCancellation(_cts.Token).ConfigureAwait(false);
Trace.WriteLine(line);
_list.Add(line);
count++;
}
}
catch (TaskCanceledException)
{
}
//await Task.Run(async () =>
//{
// int count = 0;
// while (!reader.EndOfStream)
// {
// var line = await reader.ReadLineAsync().ConfigureAwait(false);
// //var line = reader.ReadLine();
// Trace.WriteLine(line);
// count++;
// }
//});
//await Task.Factory.StartNew(() =>
//{
// int count = 0;
// while (!reader.EndOfStream)
// {
// var line = reader.ReadLine();
// Trace.WriteLine(line);
// count++;
// }
//});
BeginInvoke(new Action(() => button.Text = "Process"));
}
}
}
public static class ThreadExtensionMethods
{
public static Task<T> WithCancellation<T>(this Task<T> task, CancellationToken cancellationToken)
{
return task.IsCompleted // fast-path optimization
? task
: task.ContinueWith(
completedTask => completedTask.GetAwaiter().GetResult(),
cancellationToken,
TaskContinuationOptions.ExecuteSynchronously,
TaskScheduler.Default);
}
}
【问题讨论】:
-
如果你只是使用
var fileLines = await File.ReadAllLinesAsync(dialog.FilePath, _cts.Token);呢? -
阅读需要多少时间迫使您申请
CancellationToken? -
@CamilioTerevinto 几个注意事项:1)它是 .NET Core API 2)它是 broken API
-
每行有多大?读取线路时是否需要
CancellationToken? -
List不是线程安全的。我现在将答案更改为List,但请确保在加载数据时您没有对其进行任何操作。