Form.ShowDialog()方法导致代码暂停,直到新调用的表单关闭。我需要在调用ShowDialog()方法后继续运行代码。我用谷歌搜索并阅读有关使用backgroundworker的内容?但这是我第一次听说过,从未使用过它。
Form2 form2this = new Form2();
form2this.ShowDialog();
MessageBox.Show("Something");
此代码在单击按钮后执行,我如何仍然调用ShowDialog以防止用户与主窗体交互但仍然允许主窗体继续其工作?
很抱歉,如果已经讨论过,但我发现的一切似乎都很难执行这么简单的任务。我实际上很惊讶它不包含在SHowDialog方法中。例如ShowDialog()。继续会很酷。
答案 0 :(得分:16)
如果您只想让代码继续而不是阻止,直到弹出窗口关闭,请考虑使用Show
代替ShowDialog
。
如果您希望在子表单启动时让父表单执行某些操作,则可以使用BackgroundWorker(或者仅手动启动新的线程/任务)。了解更多关于该任务的内容将会有所帮助。如果你需要与主表格或儿童表格互动,那对我来说似乎很麻烦;如果你只是需要做一些没有UI交互的后台任务,那么这是正确的思路。
另一种可能性是,您想要做的事情应该是在子表单中完成的,而不是父表单。
答案 1 :(得分:6)
只要在打开模式对话框的过程中进行异步操作,就可以像下面所示那样简单地进行,假设button1_Click()是按钮的事件处理程序。
Future<String> futureString = asyncTimeout(10000);
futureString.get(5000, TimeUnit.MILLISECONDS);
@Async
public Future<String> asyncTimeout(long mills) throws InterruptedException {
return new AsyncResult<String>(
sleepAndWake(mills)
);
}
public String sleepAndWake(long mills) throws InterruptedException{
Thread.sleep(mills);
return "wake";
}
我发现当我使用建议使用Show()的解决方案时,我可能会在我想要模态的对话框最终在主要表单后面,在应用程序之间来回切换的情况下结束。当我使用上述解决方案时,这种情况永远不会发生。
答案 2 :(得分:0)
有没有理由不能将此代码作为Form2类的一部分?或者使用非模态对话框?你可以使用后台工作者,甚至像计时器这样的简单东西,但看起来有点过分?
答案 3 :(得分:0)
运行异步调用以显示模态。这是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 ...
}
答案 4 :(得分:0)
这是我的方式,如此丑陋,但我没有更好的主意。
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);
}
答案 5 :(得分:-1)
我想下一个异步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();
}
在主要表单中,您必须使用此代码:
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);
}
}