简体   繁体   English

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

[英]How to continue executing code after calling ShowDialog()

the Form.ShowDialog() method causes the code to be halted until the newly called form is closed. Form.ShowDialog()方法导致代码暂停,直到新调用的窗体关闭。 I need the code to continue running after the ShowDialog() method is called. 我需要在调用ShowDialog()方法后继续运行代码。 I googled and read about using backgroundworker? 我用谷歌搜索并阅读有关使用backgroundworker的内容? But that is the first time i have heard of that and never used it before. 但这是我第一次听说过,从未使用过它。

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. 我实际上很惊讶它不包含在SHowDialog方法中。 for instance ShowDialog().Continue would be cool. 例如ShowDialog()。继续会很酷。

  • If you just want the code to continue on instead of blocking until the popup is closed consider using Show instead of ShowDialog . 如果您只想让代码继续而不是阻塞,直到弹出窗口关闭,请考虑使用Show而不是ShowDialog

  • 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). 如果您希望在子表单启动时让父表单执行某些操作,那么是的,使用BackgroundWorker(或者只是手动启动新的线程/任务)可能是合适的。 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. 如果你只是需要做一些没有UI交互的后台任务,那么这是正确的思路。

  • Another possibility is that what you want to do really just should be something done in the child form, rather than the parent form. 另一种可能性是你想要做的事情应该是以子形式完成的,而不是父形式。

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. 我发现当我使用建议使用Show()的解决方案时,我可能会在我想要模态的对话框最终在主窗体后面,在应用程序之间来回切换的情况下结束。 That never happens when I use the solution above. 当我使用上述解决方案时,这种情况从未发生

Is there any reason why you can't have this code as part of the Form2 class? 你有什么理由不能将此代码作为Form2类的一部分吗? Or use a non-modal dialog? 或者使用非模态对话框? You could use a background worker or even something simple like a timer, but seems like overkill? 你可以使用后台工作者甚至像计时器一样简单的东西,但看起来有点矫枉过正?

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 ...
}

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

To continue code execution without closing modal dialog WindowsFormsSynchronizationContext.Current.Post(-=> {"Your code"}, null); 继续执行代码而不关闭模式对话框WindowsFormsSynchronizationContext.Current.Post( - => {“Your code”},null); can be used. 可以使用。 Here you can find more detail - 在这里你可以找到更多细节 -

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

I suppose next solution for async ShowDialog : 我想下一个异步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);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM