我正在尝试获取文件列表并在异步任务中迭代它们,以便UI线程可以自由更新输出窗口(或进度条)。这只是为了释放UI线程。当我使用普通的string[]
var files = new[] {"test path"});
时,效果很好
我还要注意,我已将此代码的示例与Directory.GetFiles()
一起删除。但是,每当我引入Directory
或DirecoryInfo
时,UI线程都会被阻止。无论我是在任务内部还是外部检索文件,结果都是一样的。
为什么此代码会阻止UI线程?我不一定需要异步迭代文件(这些是我在搜索主题时找到的唯一类型的答案)。我只需要获取文件列表并在异步上下文中迭代它们。
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data.SQLite;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
namespace Indexer
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private CancellationTokenSource _stopWorkingCts;
public MainWindow()
{
InitializeComponent();
}
private void StartButton_Click(object sender, RoutedEventArgs e)
{
if (_stopWorkingCts == null || _stopWorkingCts.IsCancellationRequested)
{
_stopWorkingCts = new CancellationTokenSource();
AnalyzeFiles(this);
}
}
private void AnalyzeFiles(MainWindow mainWindow)
{
UpdateWindow("Analyzing files.");
Task.Run(() =>
{
var files = Directory.GetFiles(_path, "*.dat", SearchOption.TopDirectoryOnly);
foreach (var dir in files)
{
if (!_stopWorkingCts.IsCancellationRequested)
{
mainWindow.UpdateWindow($"test {dir}");
}
else
{
break;
}
}
});
}
private void StopButton_Click(object sender, RoutedEventArgs e)
{
UpdateWindow("Connection closed.", false);
if (_stopWorkingCts != null)
{
_stopWorkingCts.Cancel();
UpdateWindow($"Stop requested.", false);
}
}
private void UpdateWindow(string text, bool queueMessage = false)
{
Dispatcher.BeginInvoke(new Action(() =>
{
if (queueMessage)
{
newOutputLines.Add($"{DateTime.Now} - {text}");
if (newOutputLines.Count >= 5)
{
OutputBox.AppendText(string.Join(Environment.NewLine, newOutputLines.ToArray()) +
Environment.NewLine);
OutputBox.ScrollToEnd();
newOutputLines.Clear();
}
}
else
{
OutputBox.AppendText(text + Environment.NewLine);
OutputBox.ScrollToEnd();
}
if (OutputBox.LineCount >= 500)
{
OutputBox.Text =
string.Join(Environment.NewLine,
OutputBox.Text.Split(new[] { Environment.NewLine }, StringSplitOptions.None)
.Skip(Math.Max(0, OutputBox.LineCount - 500)));
}
}));
}
}
}
答案 0 :(得分:1)
...当您使用GetFiles时,您必须等待整个名称数组 在您可以访问阵列之前返回。
所以GetFiles()是一个阻塞调用;只需将内部移动到您的任务中即可。
变化:
var files = Directory.GetFiles(_path, "*.dat", SearchOption.TopDirectoryOnly);
Task.Run(() =>
{
// ... rest of the code ...
要:
Task.Run(() =>
{
var files = Directory.GetFiles(_path, "*.dat", SearchOption.TopDirectoryOnly);
// ... rest of the code ...