I have an application that parses a large XML file and builds WPF UI controls based on that content. This task usually takes about 15 - 30 seconds. In order to inform the user about a running task, I display a simple intermediate progress dialog window, like:
Thread progressDialogThread = new Thread(() =>
{
Window window = new Window
{
Content = new ProgressDialog(),
Height = 100,
Width = 150,
WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen
};
window.ShowDialog();
});
progressDialogThread.SetApartmentState(ApartmentState.STA);
progressDialogThread.IsBackground = true;
progressDialogThread.Start();
buildUI();
progressDialogThread.Abort();
This works, but I sometimes get a ThreadAbortException on progressDialogThread.Start(), when the XML should be parsed once again.
Does anyone know a better approach to "close" the progress dialog?
Since the controls have to be built on the main UI thread, I can not use the backgroundworker...
The progress dialog itself in XAML looks like:
<UserControl x:Class="MyDialog.ProgressDialog"
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:MyDialog"
mc:Ignorable="d"
Background="{DynamicResource MaterialDesignPaper}"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
Height="100" Width="150">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<Label HorizontalAlignment="Center">Please wait</Label>
<ProgressBar
Style="{StaticResource MaterialDesignCircularProgressBar}"
Value="0"
IsIndeterminate="True" Width="40" Height="41" Margin="55,0" HorizontalAlignment="Center" VerticalAlignment="Center" />
</StackPanel>
</UserControl>
Do not abort a thread, that should be avoided.
If you want to close a
Window, you callCloseon it.Oh, it is created by another thread? Alright, that is why the
Windowhas aDispatcher, you useBeginInvokeand it will run the callback on that thread.In fact, there is a chance you do not need to create the
Windowin another thread※. You can create it in the main thread and have a background thread interact with it viaBeginInvoke.※: If you have the main thread busy and want the
Windowin another thread so the main thread does not block it (or viceversa), you probably should be using aBackgroundWorker(as Caius Jard suggests) instead of having a UI thread busy.