1

我有一个我想使用的 WPF 窗口,而不是常规的 Windows.MessageBox,主要是因为我希望它有一个“详细信息”框来显示错误的内容。这工作正常,直到我开始进入线程。

我想运行一个任务,该任务将获得一个列表,例如,SQL Server 数据库中的表可能需要一点时间。如果出现错误 - 在尝试连接时说超时 - 我想显示带有异常详细信息的自定义弹出窗口。

拳头它一直在崩溃。经过一些阅读(对你们这里的 SO),我突然意识到任务不在 UI 线程中并且无法显示窗口(本机 MessageBox 似乎仍然可以工作)。所以,我想出了以下内容:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        Task t = Task.Factory.StartNew(() => DoWork());
    }

    void DoWork()
    {
        Thread thread = new Thread(() =>
        {
            Window1 popup = new Window1();
            popup.Show();
            System.Windows.Threading.Dispatcher.Run();
        });

        thread.SetApartmentState(ApartmentState.STA);
        thread.Start();
    }
}

这是我制作的一个临时应用程序,因此我可以展示我正在做的事情的基础知识。在主应用程序中,我将异常作为参数发送到弹出窗口。

我的问题是:这是最好的方法吗?它似乎工作正常,但不是 100% 确定混合这样的线程是最佳实践,并认为我会把它放在那里。

如果这是一个好的解决方案,我的下一个问题是如何将弹出窗口与父窗口联系起来,以防止用户在弹出窗口打开时关闭父窗口,或者在父窗口关闭时自动关闭弹出窗口?Parent 本身不会是主要应用程序。

4

1 回答 1

4

我认为最好的方法是在应用程序的主 UI 线程上显示窗口。

你可以通过传递一个Dispatcherto 来做到这一点DoWork()。但是将执行计算和显示错误的关注点分开也是有意义的。因此,您可以做的是让DoWork()throw 并在Task. 延续只会在发生错误时运行,并将在主 UI 线程的上下文中运行:

private void button1_Click(object sender, RoutedEventArgs e)
{
    Task.Factory.StartNew(DoWork)
        .ContinueWith(
            task => ErrorBox.Show(task.Exception),
            CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted,
            TaskScheduler.FromCurrentSynchronizationContext());
}

private void DoWork()
{
    throw new Exception();
}

(假设ErrorBox.Show()创建并显示窗口。)

于 2013-04-22T20:03:56.443 回答