调用ShowDialog()后如何继续执行代码

时间:2012-11-05 19:51:38

标签: c# forms continue

Form.ShowDialog()方法导致代码暂停,直到新调用的表单关闭。我需要在调用ShowDialog()方法后继续运行代码。我用谷歌搜索并阅读有关使用backgroundworker的内容?但这是我第一次听说过,从未使用过它。

Form2 form2this = new Form2();
form2this.ShowDialog();
MessageBox.Show("Something");

此代码在单击按钮后执行,我如何仍然调用ShowDialog以防止用户与主窗体交互但仍然允许主窗体继续其工作?

很抱歉,如果已经讨论过,但我发现的一切似乎都很难执行这么简单的任务。我实际上很惊讶它不包含在SHowDialog方法中。例如ShowDialog()。继续会很酷。

6 个答案:

答案 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);
    }
}