21

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

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

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

抱歉,如果它被讨论过,但我发现的一切似乎都很难执行如此简单的任务。我实际上很惊讶它没有包含在 SHowDialog 方法中。例如 ShowDialog().Continue 会很酷。

4

6 回答 6

20
  • 如果您只是希望代码继续运行而不是阻塞直到弹出窗口关闭,请考虑使用Show而不是ShowDialog.

  • 如果您希望在子表单启动时让父表单执行某些操作,那么是的,使用 BackgroundWorker(或只是手动启动新线程/任务)可能是合适的。不过,了解更多有关该任务的信息会很有帮助。如果您需要与主窗体或子窗体交互,那对我来说似乎很麻烦;如果您只需要执行一些没有 UI 交互的后台任务,那么这是正确的思路。

  • 另一种可能性是,您真正想要做的只是应该在子表单中完成,而不是在父表单中完成。

于 2012-11-05T19:57:08.963 回答
7

只要你在模态对话框打开的时候做异步操作,你可以像下面这样简单地做,假设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);
}

我发现,当我使用建议使用 Show() 的解决方案时,在应用程序之间来回切换之后,我可能会遇到我想要成为模态的对话框最终落后于主窗体的情况。当我使用上面的解决方案时,这永远不会发生。

于 2016-01-20T18:10:54.337 回答
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);
}
于 2014-08-25T05:54:49.947 回答
0

在不关闭模式对话框的情况下继续执行代码 WindowsFormsSynchronizationContext.Current.Post(-=> {"Your code"}, null); 可以使用。在这里您可以找到更多详细信息 -

http://newapputil.blogspot.in/2015/05/continue-executing-code-after-calling.html

于 2015-05-08T10:21:02.760 回答
-1

运行异步调用以显示模式。这是 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 ...
}
于 2013-08-09T05:38:29.247 回答
-1

我想 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();
}

在主要形式中,您必须使用以下代码:

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);
    }
}
于 2014-08-27T06:35:42.040 回答