在执行某些操作时ShowDialog()

时间:2017-08-28 08:48:42

标签: c# wpf multithreading window

我正在使用Window来显示MainWindow上当前正在执行的任务。

我想做的是这样的事情:

Window progressDialog = new ProgressDialog();
using(progressDialog .ShowDialog())
{
    //Perform some tasks and Update UI on progressDialog

} // Close/Dispose the progressdialog by itself

显然ShowDialog()会阻止执行,所以我不能做某事。在MainWindow上,而另一个是shwon。

我明确需要的东西:

  1. 将/ Dialog显示为真实对话框( TopMost无法选择
    • 我想阻止用户做某事。加载时
  2. using非常好用,因为它易于使用并且可以解决长时间运行的任务。
  3. 修改

    我想到的详情:

    1. 用户点击“刷新”
    2. 创建新的“Status / Progreess-Update”
    3. 将StatusUpdate传递给ProgressWindow(橙色)(如果可能,我们从using获取该窗口)
    4. 如果有一个活动的ProgressWindow实例,请将StatusUpdate添加到其Collection中 - 否则显示新窗口
    5. 在EndOfUsing CloseWindow()
    6. 例如,“刷新”可以包含以下操作:

      1. 连接数据库
      2. 查询数据
      3. 显示数据
      4. 我希望在我的进度窗口中为每个提供一个条目。

        enter image description here

        这可能吗? - 我愿意接受替代方案:P

2 个答案:

答案 0 :(得分:0)

我在生产应用程序中完成了这项工作。这可以通过以下方式完成:

  1. 创建您自己的IDisposable进度窗口包装器
  2. 在你的包装器的构造函数中,启动一个新的STA线程,并从该线程创建并显示(使用Show(),而不是ShowDialog())进度窗口Topmost属性集到true。请务必在Dispatcher.Run()窗口之后在此主题上致电Show
  3. 通过Dispatcher.BeginInvoke来电
  4. 更新进度窗口中的所有数据
  5. 在包装器的Dispose方法中,关闭窗口并关闭线程。
  6. 编辑:可以使用Win32 api EnableWindow禁用主窗口:

    public static class WindowHelper
    {
        [DllImport("user32.dll")]
        static extern bool EnableWindow(IntPtr hWnd, bool bEnable);
    
    
        public static void DisableWindow(Window window)
        {
            EnableWindow(new WindowInteropHelper(window).EnsureHandle(), false);
    
        }
    
        public static void EnableWindow(Window window)
        {
            EnableWindow(new WindowInteropHelper(window).EnsureHandle(), true);
        }
    }
    

    编辑:在另一个线程上运行窗口的代码

    var thread = new Thread(() =>
    {
        window_ = new ProgressWindow();
        window_.Show();
    
        window_.Closed += (sender, args) =>
        {
            window_.Dispatcher.InvokeShutdown();
        };
    
        Dispatcher.Run();
    
    });
    
    thread.Name = "ProgressWindowThread";
    thread.IsBackground = true;
    thread.SetApartmentState(ApartmentState.STA);
    thread.Start();
    

    可以使用Dispatcher.BeginInvokewindow.Close()完成结算。

答案 1 :(得分:0)

  

让我们说我的进度窗口包含ListView,显示每项任务的进度条。一旦完成,我想开始下一个,更新窗口并将其添加到我的ListView。 ShowDialog()将阻止我开始另一项任务。

如果您在调用阻止ShowDialog()方法之前启动任务,则不会。以下是您的基本示例。

<强> XAML:

<ListBox x:Name="lb" />
<Button Content="Show Dialog" Click="Button_Click_1" />

<强>代码:

public MainWindow()
{
    InitializeComponent();

    Task.Run(() =>
    {
        while (true)
        {
            //simulate some long-running work...
            System.Threading.Thread.Sleep(1500);
            Dispatcher.BeginInvoke(new Action(() => lb.Items.Add("task x...")));
        }
    });
}

private void Button_Click_1(object sender, RoutedEventArgs e)
{
    Window dialog = new Window();
    dialog.ShowDialog();
}

在显示对话框时,任务将继续更新ListBox