【问题标题】:WPF Material Design Progress Dialog not shown during a task execution任务执行期间未显示 WPF 材料设计进度对话框
【发布时间】:2019-04-14 16:48:21
【问题描述】:

我尝试在后台执行某些任务时打开材料设计对话框。因此,我使用 DialogHost <materialDesign:DialogHost> 包装了 DockPanel,并使用回调委托重载了 Show 方法。

当我点击一个按钮时,应该在任务执行过程中显示一个进度对话框,例如

private async void LoadConfigButton_Click(object sender, RoutedEventArgs e)
{
            var dialogContent = new TextBlock
            {
                Text = "Loading.... Please wait.",
                Margin = new Thickness(20)
            };
            await DialogHost.Show(dialogContent,
                new DialogOpenedEventHandler((object senderDialog, DialogOpenedEventArgs args) =>
                {
                // DoStuffMethod();
                }));

}

现在,我看到了进度对话框,但只有在 "Do stuff method" 完成之后。

我在这里错过了什么?

【问题讨论】:

  • 你找到解决办法了吗?

标签: c# wpf material-design


【解决方案1】:

没有迹象表明您的

// DoStuffMethod();

也是一种异步方法。如果不是,让 Dispatcher 异步执行工作以防止阻塞

I.E.

App.Current.Dispatcher.Invoke(async () => DoStuffMethod());

我刚刚用谷歌搜索了这个,但我还记得调度程序对象应该有一个 InvokeAsync() 方法,你也可以调用它。

您可以如上所示访问调度程序,但您的控件还应该有一个可用的 Dispatcher 属性,可以以相同的方式使用。

【讨论】:

  • 我也试过这个。但它破坏了我的应用程序,因为 STA 线程之间的资源共享和 DoStuffMethod 中发生的事情(返回类型:void)
  • 啊,你需要调度员。等一下,我会编辑我的帖子
  • 与以前的行为相同。编译器给了我这个警告:CS1998 C# 这个异步方法缺少“等待”运算符,将同步运行。考虑使用“await”运算符来等待非阻塞 API 调用,或“await Task.Run(...)”在后台线程上执行 CPU 密集型工作。
  • 如果您从 UI 访问任何内容,您必须使用 UI 线程来执行 UI 更新。单元线程以类似于 Javascript 的方式运行,它可以同时执行多个独立的工作,就好像它是并行处理一样,但它实际上只是为队列中的每个任务在单个线程上调度工作。这个单元线程的管理者,至少对于 WPF,是 Dispatcher
  • 好的。我只是想通知用户正在进行的操作,所以也许我可以在单独的线程/任务中显示对话框,而不是在对话框中做事......
【解决方案2】:

当您调用 DialogHost.Show 时,DialogOpenedEventHandler is invoked synchronously

如果 DoStuffMethod 被阻塞,它将阻止对话框显示,直到它完成。如果您想在 对话框已经显示之后调用,则有几个选择。

  1. 将调用包装在 Task.Run 中。这假定它是一个 void 返回方法。如果不是,您可能需要查看其他overloads 之一。请注意,这将导致该方法在后台线程上运行。如果方法中有任何东西需要触摸 UI 元素,您将需要利用 Dispatcher.Invoke/BeginInvoke,正如其他人提到的那样。

    Task.Run(DoStuffMethod);

  2. 在 UI 的调度程序上将方法排入队列。当您使用Dispather.BeginInvoke 时,该方法将在当前调度程序队列中排队。这不是静态方法,因此您需要获取 Dispatcher 的实例(如果您正在执行 MVVM,这可能是一个问题,并且此代码在您的视图模型中)。通常,您可以直接在 UI 元素上使用 Dispatcher 属性,也可以使用静态属性 Application.Current.Dispatcher 访问其中一个。

    var dispatcher = ...

    dispatcher.BeginInvoke(DoStuffMethod);

【讨论】:

    猜你喜欢
    • 2015-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多