在 C# 中调用 showdialog 时出现 Threadabortexception
Threadabortexception when calling showdialog in C#
我有一个应用程序可以解析大型 XML 文件并基于该内容构建 WPF UI 控件。此任务通常需要大约 15 - 30 秒。为了通知用户 运行 任务,我显示一个简单的中间进度对话框 window,例如:
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();
这行得通,但我有时会在 progressDialogThread.Start()
上遇到 ThreadAbortException,此时应再次解析 XML。
有人知道 "close" 进度对话框的更好方法吗?
由于控件必须建立在主UI线程上,我不能使用后台程序...
XAML 中的进度对话框本身如下所示:
<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>
像这样的事情正是 BackgroundWorker 的用途,以及为什么它知道 UI 线程和工作线程之间的区别。使用后台工作者,在 DoWork 事件处理程序中解析您的 XML 文件(它将在后台线程上 运行 )并在执行 DoWork 循环时使用 ReportProgress 方法定期报告进度。 ProgressChanged 处理程序代码将在 UI 线程上执行,它应该弹出进度对话框以提供有关进程的状态更新
不要中止线程,应该避免这种情况。
如果你想关闭一个 Window
,你可以在上面调用 Close
。
哦,是别的线程创建的?好吧,这就是 Window
有一个 Dispatcher
的原因,你使用 BeginInvoke
它将 运行 在该线程上的回调。
事实上,您有可能不需要在另一个线程中创建 Window
※。您可以在主线程中创建它并让后台线程通过 BeginInvoke
.
与其交互
※:如果你的主线程很忙并且想要在另一个线程中使用 Window
这样主线程就不会阻塞它(反之亦然),你可能应该使用 BackgroundWorker
(作为 ) 而不是让 UI 线程忙。
我有一个应用程序可以解析大型 XML 文件并基于该内容构建 WPF UI 控件。此任务通常需要大约 15 - 30 秒。为了通知用户 运行 任务,我显示一个简单的中间进度对话框 window,例如:
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();
这行得通,但我有时会在 progressDialogThread.Start()
上遇到 ThreadAbortException,此时应再次解析 XML。
有人知道 "close" 进度对话框的更好方法吗?
由于控件必须建立在主UI线程上,我不能使用后台程序...
XAML 中的进度对话框本身如下所示:
<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>
像这样的事情正是 BackgroundWorker 的用途,以及为什么它知道 UI 线程和工作线程之间的区别。使用后台工作者,在 DoWork 事件处理程序中解析您的 XML 文件(它将在后台线程上 运行 )并在执行 DoWork 循环时使用 ReportProgress 方法定期报告进度。 ProgressChanged 处理程序代码将在 UI 线程上执行,它应该弹出进度对话框以提供有关进程的状态更新
不要中止线程,应该避免这种情况。
如果你想关闭一个 Window
,你可以在上面调用 Close
。
哦,是别的线程创建的?好吧,这就是 Window
有一个 Dispatcher
的原因,你使用 BeginInvoke
它将 运行 在该线程上的回调。
事实上,您有可能不需要在另一个线程中创建 Window
※。您可以在主线程中创建它并让后台线程通过 BeginInvoke
.
※:如果你的主线程很忙并且想要在另一个线程中使用 Window
这样主线程就不会阻塞它(反之亦然),你可能应该使用 BackgroundWorker
(作为