C# 调用 ShowDialog() 后如何继续执行代码
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13239306/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to continue executing code after calling ShowDialog()
提问by Seth
the Form.ShowDialog() method causes the code to be halted until the newly called form is closed. I need the code to continue running after the ShowDialog() method is called. I googled and read about using backgroundworker? But that is the first time i have heard of that and never used it before.
Form.ShowDialog() 方法会导致代码暂停,直到新调用的窗体关闭。我需要代码在调用 ShowDialog() 方法后继续运行。我在谷歌上搜索并阅读了有关使用后台工作人员的信息?但这是我第一次听说,以前从未使用过。
Form2 form2this = new Form2();
form2this.ShowDialog();
MessageBox.Show("Something");
This code gets executed after clicking a button, how can i still call ShowDialog to prevent the user from interacting with the main form but still allowing the main form to continue with its work?
单击按钮后会执行此代码,我如何仍然调用 ShowDialog 以防止用户与主窗体交互但仍允许主窗体继续其工作?
Sorry if its been discussed but everything i found seems extremely difficult to perform such a simple task. I am actually surprised its not included in the SHowDialog method. for instance ShowDialog().Continue would be cool.
对不起,如果它被讨论过,但我发现的一切似乎很难执行这样一个简单的任务。我实际上很惊讶它没有包含在 SHowDialog 方法中。例如 ShowDialog().Continue 会很酷。
采纳答案by Servy
If you just want the code to continue on instead of blocking until the popup is closed consider using
Showinstead ofShowDialog.If you have some action that you want to have the parent form doing while the child form is up, then yes, it could be appropriate to use a BackgroundWorker (or just manually starting a new Thread/Task). It would be helpful to know more about what that task is though. If you need to interact with the main form, or the child form, then that seems like trouble to me; if you just need to do some background task with no UI interaction then this is the right line of thought.
Another possibility is that what you want to do really just should be something done in the child form, rather than the parent form.
如果您只想让代码继续运行而不是阻塞直到弹出窗口关闭,请考虑使用
Show代替ShowDialog。如果您希望在子表单启动时让父表单执行某些操作,那么是的,使用 BackgroundWorker(或仅手动启动新线程/任务)可能是合适的。不过,了解更多有关该任务的内容会很有帮助。如果您需要与主窗体或子窗体交互,那对我来说似乎很麻烦;如果您只需要在没有 UI 交互的情况下执行一些后台任务,那么这是正确的思路。
另一种可能性是,您真正想做的应该是在子表单中完成的事情,而不是在父表单中。
回答by Fergal Moran
Is there any reason why you can't have this code as part of the Form2 class? Or use a non-modal dialog? You could use a background worker or even something simple like a timer, but seems like overkill?
有什么理由不能将此代码作为 Form2 类的一部分吗?还是使用非模态对话框?您可以使用后台工作人员,甚至可以使用诸如计时器之类的简单工具,但似乎有点矫枉过正?
回答by Bj?rn Frohberg
Run an async call to show modal. Here an example in wpf:
运行异步调用以显示模态。这是 wpf 中的一个示例:
private Window waitView;
/// <summary>
/// Closes a displayed WaitView from code.
/// </summary>
public void CloseWaitView()
{
if(waitView != null)
{
// Work on the gui Thread of waitView.
waitView.Dispatcher.Invoke(new Action(() => close()));
}
}
/// <summary>
/// Closes a displayed WaitView and releases waitView-Instance.
/// </summary>
private void close()
{
waitView.Close();
waitView = null;
}
/// <summary>
/// Showes a modal WaitView (Window).
/// </summary>
public void ShowWaitView()
{
// instance a new WaitViewWindow --> your Window extends Window-Class
waitView = new WaitViewWindow();
// prepare a operation to call it async --> your ShowDialog-call
var asyncCall = new Action(() => waitView.Dispatcher.Invoke(
new Action(() => waitView.ShowDialog())
));
// call the operation async
// Argument 1 ar:
// ar means IAsyncResult (what should be done, when come back from ShowDialog -->
// remove view memory with set waitView to null or ... dispose
// the second argument is an custom parameter you can set to use in ar.AsyncState
asyncCall.BeginInvoke(ar => waitView = null, null);
// all from here is done during ShowDialog ...
}
回答by IlPADlI
This is my way, so ugly but i have no better idea.
这是我的方式,很丑,但我没有更好的主意。
private void AppUiMain_Shown(object sender, EventArgs e)
{
var loading = new AppUiLoading();
loading.Shown += (o, args) =>
{
bool isLoading = true;
loading.Top = (int)(loading.Top * 1.16);
Application.DoEvents();//refresh ui
EventHandler ehr = null;
EventHandler ehe = null;
ehr = (ss, ee) =>
{
App.Instance.Ready -= ehr;
App.Instance.Error -= ehe;
isLoading = false;
};
ehe = (ss, ee) =>
{
loading.Text = "Error";
loading.ShowAbortButton("Error occur");
};
App.Instance.Error += ehe;
App.Instance.Ready += ehr;
InitApp();
//HACK: find a better way to `refresh' main form
Application.DoEvents();
this.Height++;
this.Height--;
//HACK: find a better way to keep message looping on ShowDialog
while (isLoading)
Application.DoEvents();
loading.Close();
};
loading.ShowDialog(this);
}
回答by Ivan Kochurkin
I suppose next solution for async ShowDialog:
我想 async 的下一个解决方案ShowDialog:
public bool DialogResultAsync
{
get;
private set;
}
public async Task<bool> ShowDialogAsync()
{
var cts = new CancellationTokenSource();
// Attach token cancellation on form closing.
Closed += (object sender, EventArgs e) =>
{
cts.Cancel();
};
Show(); // Show message without GUI freezing.
try
{
// await for user button click.
await Task.Delay(Timeout.Infinite, cts.Token);
}
catch (TaskCanceledException)
{ }
}
public void ButtonOkClick()
{
DialogResultAsync = true;
Close();
}
public void ButtonCancelClick()
{
DialogResultAsync = false;
Close();
}
And in main form you must use this code:
在主要形式中,您必须使用以下代码:
public async void ShowDialogAsyncSample()
{
var msg = new Message();
if (await msg.ShowDialogAsync())
{
// Now you can use DialogResultAsync as you need.
System.Diagnostics.Debug.Write(msg.DialogResultAsync);
}
}
回答by nvivekgoyal
To continue code execution without closing modal dialog WindowsFormsSynchronizationContext.Current.Post(-=> {"Your code"}, null); can be used. Here you can find more detail -
在不关闭模式对话框的情况下继续执行代码 WindowsFormsSynchronizationContext.Current.Post(-=> {"Your code"}, null); 可以使用。在这里你可以找到更多细节——
http://newapputil.blogspot.in/2015/05/continue-executing-code-after-calling.html
http://newapputil.blogspot.in/2015/05/continue-executing-code-after-calling.html
回答by Joe Savage
As long as you do asynchronous operations during the time that the modal dialog is opened, you can do it as simply as shown below, assuming button1_Click() is the event handler for a button.
只要在模态对话框打开期间进行异步操作,就可以简单地进行如下所示,假设 button1_Click() 是按钮的事件处理程序。
private async void button1_Click(object sender, EventArgs e)
{
// create and display modal form
Form2 modalForm = new Form2();
BeginInvoke((Action)(() => modalForm.ShowDialog()));
// do your async background operation
await DoSomethingAsync();
// close the modal form
modalForm.Close();
}
private async Task DoSomethingAsync()
{
// example of some async operation....could be anything
await Task.Delay(10000);
}
I found that when I used the solution that suggested to use Show(), I could end up in cases where the dialog I wanted to be modal would end up behind the main form, after switching back and forth between apps. That never happens when I use the solution above.
我发现,当我使用建议使用 Show() 的解决方案时,在应用程序之间来回切换后,我可能会遇到我想要模态的对话框最终位于主窗体后面的情况。当我使用上面的解决方案时,这永远不会发生。

