gpt4 book ai didi

c# - Windows 窗体 : UI threads flow with Show() and ShowDialog()

转载 作者:行者123 更新时间:2023-11-30 14:31:13 25 4
gpt4 key购买 nike

在 Windows 窗体上开发解决方案时,我习惯于向用户展示持续的进展。我实现了带有连续进度条的简单虚拟窗口:

Continuos progress window

在解决方案树中,它与主窗口位于同一级别:

Windows forms solution tree

在做某事时显示持续进展的最简单的工作方法是以下代码。它有效:

//This method works
private void DoSomeBackgroundStuffWithShow()
{
ContinuousProgressWindow continuousProgressWindow =
new ContinuousProgressWindow();
BackgroundWorker backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += (sender, arguments) =>
{
//Do some stuff for 4 seconds
Thread.Sleep(4000);
};
backgroundWorker.RunWorkerCompleted += (sender, arguments) =>
{
//Window is closed when needed. Great!
continuousProgressWindow.Dispose();
};
continuousProgressWindow.Show(this);
backgroundWorker.RunWorkerAsync();
}

但我需要此窗口显示在最顶层 并在工作时阻止其父窗口。以下代码非常相似,但它不起作用 - 显示对话框,但从未关闭:

//This method DOES NOT WORK
private void DoSomeBackgroundStuffWithShowDialog()
{
ContinuousProgressWindow continuousProgressWindow =
new ContinuousProgressWindow();
BackgroundWorker backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += (sender, arguments) =>
{
//Do some important stuff for 4 seconds
Thread.Sleep(4000);
};
backgroundWorker.RunWorkerCompleted += (sender, arguments) =>
{
//None of the following work for "ShowDialog() method"
//Ran with debugger - breakpoints not hit!
continuousProgressWindow.DialogResult = DialogResult.OK;
continuousProgressWindow.Close();
continuousProgressWindow.Dispose();
};
continuousProgressWindow.ShowDialog(this);
backgroundWorker.RunWorkerAsync();
}

然后,我意识到问题出在 UI 线程流上:当进度窗口作为对话框运行时,MainWindow 线程被卡住,它无法被 BackgroundWorker 调用在 RunWorkerCompleted 委托(delegate)中关闭对话框。

让它按需工作的最简单解决方案是什么?

最佳答案

  continuousProgressWindow.ShowDialog(this);
backgroundWorker.RunWorkerAsync();

您遇到了一个简单的先有鸡还是先有蛋的问题,直到对话框关闭之后您才启动 worker。 ShowDialog() 是一个阻塞调用。所以 RunWorkerCompleted 事件不会触发,因为工作人员没有开始。最简单的解决方法是交换两个语句:

  backgroundWorker.RunWorkerAsync();
continuousProgressWindow.ShowDialog(this);

这样做并不完全安全。此代码段没有问题,但在实际代码中存在工作人员在显示对话框之前完成的危险。赔率低但不为零。要解决这个问题,您需要延迟 worker,直到您确定对话已启动并正在运行。这可以通过对话框的 OnShown() 方法使用 Set() 的 AutoResetEvent 来完成。或者,更优雅地,利用一个技巧:

  this.BeginInvoke(new Action(() => backgroundWorker.RunWorkerAsync()));
continuousProgressWindow.ShowDialog(this);

Control.BeginInvoke() 的委托(delegate)目标在程序重新进入消息循环时运行。这发生在对话框变得可见之后:)

关于c# - Windows 窗体 : UI threads flow with Show() and ShowDialog(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20879867/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com