C
C#2mo ago
Budzique

EnumerateFiles Blocks UI thread even in Task.Run()

I'm writing an application that needs to validate a user-given directory by searching for specific files in said directory. I'd like to run the validation in the background so the app doesn't freeze up. I've tried a few suggestions and still ended up here asking because it seems EnumerateFiles refuses to run on another thread. Following is a functional example as a .net8 WPF application.
7 Replies
Budzique
BudziqueOP2mo ago
using Microsoft.Win32;
using System.IO;
using System.Windows;

namespace threadTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}

private async Task LiveryValidate(string folderName, string extensionToFind)
{
await Task.Run(() =>
{
try
{
IEnumerable<string>? ddsFiles = Directory.EnumerateFiles(folderName, "*."+extensionToFind, SearchOption.AllDirectories);
string fullpath = ddsFiles.First().ToString();
string dirname = Path.GetDirectoryName(fullpath)!;
if (dirname != null)
{
Console.WriteLine("Found");
}
}
catch (Exception ex)
{
Console.WriteLine("Not Found");
Console.WriteLine(ex.Message);
}
});
}

private void button_Click(object sender, RoutedEventArgs e)
{
OpenFolderDialog folderDialog = new OpenFolderDialog();
if (folderDialog.ShowDialog() == true)
{
string? folderName = folderDialog.FolderName;
textBox.Text = folderName;
_ = LiveryValidate(folderName, "DDS");

}
}
}
}
using Microsoft.Win32;
using System.IO;
using System.Windows;

namespace threadTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}

private async Task LiveryValidate(string folderName, string extensionToFind)
{
await Task.Run(() =>
{
try
{
IEnumerable<string>? ddsFiles = Directory.EnumerateFiles(folderName, "*."+extensionToFind, SearchOption.AllDirectories);
string fullpath = ddsFiles.First().ToString();
string dirname = Path.GetDirectoryName(fullpath)!;
if (dirname != null)
{
Console.WriteLine("Found");
}
}
catch (Exception ex)
{
Console.WriteLine("Not Found");
Console.WriteLine(ex.Message);
}
});
}

private void button_Click(object sender, RoutedEventArgs e)
{
OpenFolderDialog folderDialog = new OpenFolderDialog();
if (folderDialog.ShowDialog() == true)
{
string? folderName = folderDialog.FolderName;
textBox.Text = folderName;
_ = LiveryValidate(folderName, "DDS");

}
}
}
}
<Window x:Class="threadTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:threadTest"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Button x:Name="button" Content="Button" HorizontalAlignment="Left" Margin="585,69,0,0" VerticalAlignment="Top" Click="button_Click"/>
<TextBox x:Name="textBox" HorizontalAlignment="Left" Margin="235,74,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="310" Height="20"/>

</Grid>
</Window>
<Window x:Class="threadTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:threadTest"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Button x:Name="button" Content="Button" HorizontalAlignment="Left" Margin="585,69,0,0" VerticalAlignment="Top" Click="button_Click"/>
<TextBox x:Name="textBox" HorizontalAlignment="Left" Margin="235,74,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="310" Height="20"/>

</Grid>
</Window>
Budzique
BudziqueOP2mo ago
Stack Overflow
EnumerateFiles Blocks UI thread even in Task.Run()
I'm writing an application that needs to validate a user-given directory by searching for specific files in said directory (in my case DDS files). I'd like to run the validation in the background s...
jcotton42
jcotton422mo ago
that definitely looks right you probably want button_Click to be async void so you can await LiveryValidate, but that shouldn't be causing UI lockups
Budzique
BudziqueOP2mo ago
Its odd, I think it looks right too, but it can't be like a .net bug can it? Also, adding async to button_Click and await to LiveryValidate didn't change, still locks the UI while scanning. This is a functional example from my main project and all it does is basically show a green message for validation. It seems like such a headache but userfriendliness is my goal. ugh. Any alternative methods to achieve the same goal without blocking the UI thread?
jcotton42
jcotton422mo ago
how does the blocking present itself? the window gets that white tint after a while?
Budzique
BudziqueOP2mo ago
entire app becomes unresponsive
jcotton42
jcotton422mo ago
@Budzique odd. I'd hop over to #gui.

Did you find this page helpful?