C# 在progressbar WPF C中异步读取大型txt文件并报告进度#
我正在尝试异步读取一个较大的txt文件(>50MB),在读取过程中,在UI进度栏上报告进度,并可以选择取消该过程。到目前为止,我已经按照我的要求读取和处理了文件async,但是我无法解决progressbar部分C# 在progressbar WPF C中异步读取大型txt文件并报告进度#,c#,wpf,asynchronous,progress-bar,reporting,C#,Wpf,Asynchronous,Progress Bar,Reporting,我正在尝试异步读取一个较大的txt文件(>50MB),在读取过程中,在UI进度栏上报告进度,并可以选择取消该过程。到目前为止,我已经按照我的要求读取和处理了文件async,但是我无法解决progressbar部分 public static async Task<string> ReadTxtAsync(string filePath) { try { using (var reader = File.OpenText(
public static async Task<string> ReadTxtAsync(string filePath)
{
try
{
using (var reader = File.OpenText(filePath))
{
var content = await reader.ReadToEndAsync();
return content;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return null;
}
}
public static async Task<Dictionary<string, int>> OpenTxtAsync()
{
Dictionary<string, int> uniqueWords = new Dictionary<string, int>();
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "Text Documents (*.txt)|*.txt";
string content = null;
try
{
if (openFileDialog.ShowDialog() == true)
{
string filePath = openFileDialog.FileName.ToString();
if (openFileDialog.CheckFileExists && new[] { ".txt" }.Contains(Path.GetExtension(filePath).ToLower()) && filePath != null)
{
Task<string> readText = ReadTxtAsync(filePath);
content = await readText;
uniqueWords = WordExtractor.CountWords(ref content);
}
else MessageBox.Show("Please use .txt format extension!");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return uniqueWords;
}
private async void LoadFileButtonClick(object sender, RoutedEventArgs e)
{
Task<Dictionary<string, int>> dictionaryContent = TextFileLoader.OpenTxtAsync();
uniqueWords = await dictionaryContent;
UpdateListView();
}
我有一个cancel
cts.cancel()的按钮点击事件代码>但它唯一起作用的部分是创建字典。如果我放置cancellationToken.ThrowIfCancellationRequested()代码>进入progressbar更新部分,它仅停止更新,流读取仍在继续。如果我放置在var readTask=reader.ReadToEndAsync()的正下方
它什么也不做。通过定期检查Stream.position
属性,可以在读取时获取当前位置。以下方法将每100毫秒检查一次当前位置,并通过progress
参数的current
值进行报告。要使用此方法,请实例化proges并订阅其ProgressChanged
事件
public static async Task<string> ReadTextAsync(string filePath, IProgress<(double current, double total)> progress)
{
using var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
using var reader = new StreamReader(stream);
var readTask = reader.ReadToEndAsync();
var progressTask = Task.Run(async () =>
{
while (stream.Position < stream.Length)
{
await Task.Delay(TimeSpan.FromMilliseconds(100));
progress.Report((stream.Position, stream.Length));
}
});
await Task.WhenAll(readTask, progressTask);
return readTask.Result;
}
公共静态异步任务ReadTextAsync(字符串文件路径,IProgress进程)
{
使用var stream=newfilestream(filePath,FileMode.Open,FileAccess.Read);
使用var reader=newstreamreader(流);
var readTask=reader.ReadToEndAsync();
var progressTask=Task.Run(异步()=>
{
while(stream.Position
您是通过什么媒介阅读的?从现代HDD(我甚至不写SSD)读取50 Mb ReadToEndAsync文件只需不到一秒钟的时间。您甚至没有时间查看任何进度。您可以使用StringBuilder
逐行读取文件,ReadToEndAsync
是原子的,您无法跟踪其进度。@EldHasp我编写了50MB作为示例,目前我使用150-300MB测试它。我知道它不需要太多时间(特别是SSD),但分配说明它必须保持响应,并且必须有一个进度条,而不管文件大小。问题被错误地解决了,所提到的重复项都与异步文件读取无关,这是我在这里主要关心的问题,我关于取消ReadToEndAsync方法的问题仍然存在。@Nyariszalami您可以找到一些示例来实现取消读取方法。这取决于你。
public static async Task<string> ReadTextAsync(string filePath, IProgress<(double current, double total)> progress)
{
using var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
using var reader = new StreamReader(stream);
var readTask = reader.ReadToEndAsync();
var progressTask = Task.Run(async () =>
{
while (stream.Position < stream.Length)
{
await Task.Delay(TimeSpan.FromMilliseconds(100));
progress.Report((stream.Position, stream.Length));
}
});
await Task.WhenAll(readTask, progressTask);
return readTask.Result;
}