Как продолжить выполнение кода после вызова ShowDialog()

форме.Метод ShowDialog () вызывает остановку кода, пока вновь вызываемая форма не будет закрыта. Мне нужен код для продолжения работы после вызова метода ShowDialog (). Я погуглил и прочитал об использовании backgroundworker? Но это первый раз, когда я слышал об этом и никогда не использовал его раньше.

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

этот код выполняется после нажатия кнопки, как я могу вызвать ShowDialog, чтобы предотвратить взаимодействие пользователя с основной формой, но все же разрешить основная форма продолжить свою работу?

Извините, если его обсуждали, но все, что я нашел, кажется чрезвычайно сложным для выполнения такой простой задачи. Я действительно удивлен, что он не включен в метод SHowDialog. например, ShowDialog ().Дальше будет круто.

7 ответов


  • если вы просто хотите, чтобы код продолжался, а не блокировался, пока всплывающее окно не будет закрыто, рассмотрите возможность использования Show вместо ShowDialog.

  • если у вас есть какое-то действие, которое вы хотите, чтобы родительская форма делала, пока дочерняя форма включена, тогда да, было бы целесообразно использовать BackgroundWorker (или просто вручную запустить новый поток/задачу). Было бы полезно узнать больше о том, что это за задача. Если вам нужно взаимодействовать с главным форма или дочерняя форма, тогда это кажется мне проблемой; если вам просто нужно выполнить какую-то фоновую задачу без взаимодействия с UI, то это правильная линия мысли.

  • другая возможность заключается в том, что то, что вы хотите сделать, действительно должно быть сделано в дочерней форме, а не в родительской форме.


пока вы выполняете асинхронные операции во время открытия модального диалога, вы можете сделать это так же просто, как показано ниже, предполагая, что 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 (), я мог бы оказаться в тех случаях, когда диалог, который я хотел бы быть модальным, окажется позади основной формы после переключения между приложениями. Это никогда не происходит, когда я использую решение выше.


есть ли причина, почему вы не можете иметь этот код как часть класса Form2? Или использовать немодальный диалог? Вы можете использовать фоновый поток worker или даже что-то простое, как таймер, но кажется излишним?


выполнить асинхронный вызов, чтобы показать модальное. Вот пример в 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 ...
}

Это мой путь, так уродливо, но у меня нет лучшей идеи.

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

продолжить выполнение кода без закрытия модального диалогового окна WindowsFormsSynchronizationContext.Текущий.Post (- => {"ваш код"}, null); может использоваться. Здесь вы можете найти более подробную информацию -

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


Я полагаю, следующее решение для 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);
    }
}