繁体   English   中英

如何在加载窗口之前使用 Dispatcher.PushFrame?

[英]How to use Dispatcher.PushFrame before the Window is loaded?

我有一个功能,我必须同步等待用户输入。 我无法控制从哪个线程调用此函数,因此调用者可能已经在 UI 线程中(在这种情况下,我将不得不使用 Dispatcher)。

为此,我一直在使用DispatcherFrameDispatcher.PushFrame ,以便 UI 继续响应,即使从 UI 线程调用函数也是如此。

这是一个小演示(请注意,这是一个非常愚蠢的示例,但这代表了我正在努力实现的目标):

主窗口.xaml

<StackPanel VerticalAlignment="Center"
            HorizontalAlignment="Center"
            Orientation="Vertical"
            Width="500">
    <TextBox x:Name="TextBox_Result"
             Margin="0 0 0 10" />

    <Button x:Name="Button_ContinueExecution"
            Content="..." />
</StackPanel>

主窗口.xaml.cs

string PromptUserForInputSynchronously()
{
    string result = null;

    if (Application.Current.Dispatcher.CheckAccess())
    {
        var nestedFrame = new DispatcherFrame(true);

        Button_ContinueExecution.Click += (s, e) =>
        {
            nestedFrame.Continue = false;
            result = TextBox_Result.Text;
        };

        Button_ContinueExecution.Content = "Click to resume execution";

        Console.WriteLine("Waiting for click...");

        Dispatcher.PushFrame(nestedFrame);

        Console.WriteLine("Clicked with text: " + result);
    }
    else
    {
        result = Dispatcher.CurrentDispatcher.Invoke(() => PromptUserForInputSynchronously());
    }

    return result;
}

现在,这似乎有效,除非(我猜) MainWindow 尚未加载。 看一看:

public MainWindow()
{
    InitializeComponent();

    // This works
    Loaded += (s, e) => PromptUserForInputSynchronously();

    // This hangs the application
    PromptUserForInputSynchronously();
}

有什么办法可以使这项工作? 这是最好的方法吗?

@edit:背景

我想要实现的是创建一个像MessageBox一样的对话框(但看起来更好)。 显示时,对话框会阻止当前线程(但保持 UI 响应,以防该线程是 Dispatcher 线程),直到用户单击其中一个按钮。

我的目标是稍后以 NuGet 包的形式提供它,这就是我在不同场景中测试它的原因(比如从构造函数内部调用它)。

您的代码抛出错误的原因是 Dispatcher 尚未启动。 默认情况下,您的入口点将实例化 MainWindow 以显示它。 确切的细节不是我曾经发现的用途,但是 Dispatcher 也已启动。 显然,直到实例化主窗口之后才会发生这种情况。

因此,您必须更改一些启动基础才能使其“正常工作”。

您可以覆盖应用程序启动并尝试在实例化主窗口之前确保 sta 线程和调度程序正在运行。 不过这是个坏主意。

除了在主窗口构造函数中实例化之外,您不应该尝试做任何事情。 原因是如果您遇到任何错误,您根本没有主窗口。 您的应用程序将关闭,您的用户将开始抱怨。

我建议您将此原则扩展到任何和所有 wpf 窗口。 尽量减少你在他们的构造函数中所做的事情。 不要中断实例化,特别是不要尝试从窗口的 ctor 中显示其他窗口。

如果您需要在显示窗口之前抛出一条消息或获取一些用户输入,那么只需首先单独执行此操作。 如果您需要显示带有模态对话框的窗口,请先显示该窗口,然后使用稍后的事件来驱动您的对话 - 显示。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM