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

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

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

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

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

 Brad05 нояб. 2012 г., 21:01
Parentform.Enabled = false
 Servy05 нояб. 2012 г., 20:57
Какие вещи вы хотите сделать, пока отображается детская форма? Вы меняете родительскую форму, взаимодействуете с дочерней формой, выполняете не-пользовательский интерфейс? ?

Ответы на вопрос(7)

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

Запустите асинхронный вызов, чтобы показать модальное. Вот пример в wpf:

private Window waitView;

/// 
/// Closes a displayed WaitView from code.
/// 
public void CloseWaitView()
{
  if(waitView != null)
  {
     // Work on the gui Thread of waitView.
     waitView.Dispatcher.Invoke(new Action(() => close()));
  }
}

/// 
/// Closes a displayed WaitView and releases waitView-Instance.
///     
private void close()
{
   waitView.Close();
   waitView = null;
}   

/// 
/// Showes a modal WaitView (Window).
/// 
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 ...
}

Я полагаю, следующее решение для асинхронного:ShowDialog

public bool DialogResultAsync
{
    get;
    private set;
}

public async Task 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);
    }
}

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

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

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

Решение Вопроса

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

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

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

 Seth05 нояб. 2012 г., 23:25
И я прошу прощения за отсутствие опыта, я только самоучка и учусь на YouTube / Web и не занимаюсь программированием изо дня в день. Поэтому я очень ценю сотрудничество всех вас и еще раз спасибо @Brad за идею! С наилучшими пожеланиями, Сет
 Seth05 нояб. 2012 г., 23:24
Большое спасибо за ваш ответ и ваши общие знания и за то, что вы хотите, чтобы я сделал что-то правильное. Я действительно ценю тот факт, что вы хотите, чтобы я учился правильно. Это имеет большой смысл, используя BackgroundWorker или Task. Но я никогда не использовал их раньше в этой усадьбе. Я действительно использовал Брэдаs метод ParentForm.Enabled = false после вызова Show. Затем я использовал обработчик событий, чтобы дождаться закрытия дочерней формы, затем, как только он закрылся, я снова включил родительскую форму. И это на самом деле смешивается довольно плавно, делая родительскую форму серой. Большое спасибо всем вам
 Seth05 нояб. 2012 г., 22:48
задачи. Так как взаимодействие с родительской формой приведет к ошибкам в выполняемой задаче.
 Servy05 нояб. 2012 г., 22:51
@Seth Просто будьте осторожны, когда вы реализуете решение, соответствующее вашей конкретной задаче, а не взламываете решение, разработанное для поддержки другого сценария. Основываясь на ваших изменениях, похоже, что это здесь. Так как тыдействительно выполняем фоновое задание, и нене нужно на самом деле взаимодействовать с пользовательским интерфейсом, пока этопроисходит, вы должны начатьBackgroundWorker или жеTask чтобы выполнить долгосрочное задание, затем после запуска показать диалоговую форму, используя.ShowDialog
 Seth05 нояб. 2012 г., 22:46
Спасибо. Причина, по которой я не могу использовать Show вместо ShowDialog, заключается в том, что я не хочу, чтобы пользователь мог взаимодействовать с parentForm. Однако я мог бы включить параметр parentForm.Enabled = false при использовании метода Show. Затем, как только вызывается метод show и отображается дочерняя форма, после закрытия она снова включает родительскую форму. Я вызываю вторую форму, в которую встроен таймер для автоматического закрытия, когда таймер включен. Вторая форма - это в значительной степени просто форма с ярлыками на ней, указывающая на терпение, так как родительская форма занимает некоторое время

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

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

Ваш ответ на вопрос