I am trying to get a list of files and iterate them within an asynchronous task so the UI thread is free to update an output window (or progress bar). This is simply to free up the UI thread. When I use a plain old string[]
(var files = new[] {"test path"});
it works great.
I'll also note that I have an example of this code working with Directory.GetFiles()
removed. However, any time I introduce Directory
or DirecoryInfo
, the UI thread is being blocked. The result is the same whether I retrieve the files inside or outside of the task.
Why does this code block the UI thread? I don't necessarily need to asynchronously iterate the files (these are the only type of answers I find when I search the topic). I just need to get a list of the files and iterate over them within an async context.
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)));
}
}));
}
}
}