【问题标题】:Simple Loading Form/Threading简单的加载形式/线程
【发布时间】:2011-04-15 20:44:13
【问题描述】:

在旧版应用程序中,我们有一个单一的 winform,在单击按钮执行代码时锁定......好吧,它不会锁定它,只是“停止响应”直到代码执行。

将下面的代码包装到单独的线程中并在执行时显示加载窗口 (frmLoading) 的最佳(代码量和工作量最少)方法是什么?我知道这应该相对简单,但我尝试了一些尚未完全解决的不同方法。

private void btnSynch_Click(object sender, EventArgs e)
{
    btnSynch.Enabled = false;

    if(chkDBSynch.Checked)
        PerformDBSyncronization();

    if(chkAppSynch.Checked)
        PerformApplicationSyncronization();

    btnSynch.Enabled = true;
}

编辑: 好的,我应该提到已经尝试过 backgroundworker,但我知道我在哪里绊倒了......这段代码将执行并且加载表单被抛在主表单后面,这就是我认为它不起作用的原因。谁能告诉我如何防止这种情况发生?

  private void btnSynch_Click(object sender, EventArgs e)
    {

        btnSynch.Enabled = false;
        frmLoading loadingWindow = new frmLoading();
        loadingWindow.Show();

        BackgroundWorker bw = new BackgroundWorker();
        bw.DoWork += (s, args) =>
        {

            Thread.Sleep(6000); //TODO:just for testing 
            if(chkDBSynch.Checked)
            PerformDBSyncronization();

            if(chkAppSynch.Checked)
            PerformApplicationSyncronization();
        };
        bw.RunWorkerCompleted += (s, args) =>
        {
            loadingWindow.Close();
        };
        bw.RunWorkerAsync();

        btnSynch.Enabled = true;
    }

【问题讨论】:

  • 您是否需要知道何时完成,或者这是“一劳永逸”的场景?
  • @Richard DesLonde - 我不需要知道它什么时候完成,只需要告诉用户表单没有“冻结”。

标签: c# winforms multithreading


【解决方案1】:

我觉得很傻......加载表单在主表单后面弹出,这就是为什么我认为它没有打开。我将 TopMost 属性设置为 true,一切都按预期工作。

编辑:
这是一个很好的解释为什么我的窗体在我的窗口后面弹出,我只是没想到打开窗口的线程不使用主窗体作为所有者。

Why use a owner window in MessageBox.Show?

我的代码看起来像

        frmLoading loadingWindow = new frmLoading();
        loadingWindow.Show(this);

        BackgroundWorker bw = new BackgroundWorker();
        bw.DoWork += (s, args) =>
        {
            this.Invoke(new MethodInvoker(() => this.Enabled = false));

            if(chkDBSynch.Checked)
            PerformDBSyncronization();

            if(chkAppSynch.Checked)
            PerformApplicationSyncronization();
        };
        bw.RunWorkerCompleted += (s, args) =>
        {
            loadingWindow.Close();
            this.Invoke(new MethodInvoker(() => this.Enabled = true));

        };

        bw.RunWorkerAsync();

【讨论】:

  • 将加载表单的所有者设置为主表单:loadingForm.ShowDialog(this).
  • @Tergiver - 谢谢,这实际上是我最终做的,但我没有使用 ShowDialog 因为主窗体会等待结果。 (我只是将最顶层的属性设置为快速测试)...我会更新我的答案。
  • 使用 ShowDialog 可以防止用户与所有者窗口进行交互,它不会“等待结果”。 UI 线程仍将发送消息,所有者窗口仍将“活动”。如果您使用 Show,用户可以与您的主窗口进行交互,从而导致加载表单消失,并激活可能尚未准备好激活的控件。
  • @Tergiver - 我听到你的声音,这当然是我认为它的工作原理,但当我尝试使用 showdialog 时,情况并非如此......主窗体上的断点从未被击中......可能是因为我实现多线程的方式和调用 ShowDialog 的点?
  • 看起来您正在禁用主窗口并使用Show,这实际上与ShowDialog 相同。如果您想弄清楚为什么不能使用 ShowDialog,请制作一个简单的演示并将其作为新问题发布。
【解决方案2】:

为此使用BackgroundWorker。

【讨论】:

  • 我试过后台工作者,但我做错了什么。加载表单永远不会弹出......我有点希望有人有一些代码示例。
  • This 是一个非常友好的介绍。如果您可以访问C# 2008 Express Edition: Build a program now 这本书,它里面有一个很好的例子。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多