简体   繁体   English

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

[英]Continue code execution after calling ShowDialog()

I am trying to open a loading window while the else code keeps executing in the background, and close it whenever required (without threading).我试图在 else 代码在后台继续执行时打开一个加载窗口,并在需要时关闭它(无线程)。

Something like this:像这样的东西:

LoadingWindow.ShowDialog();
Thread.Sleep(2000);     //Simulates slowness
AnotherForm.ShowDialog();
LoadingWindow.Close(); //After AnotherForm displayed.

I can't use only LoadingWindow.Show();我不能只使用LoadingWindow.Show(); to continue execution because LoadingWindow will not display correctly till the code after LoadingWindow.Show();继续执行,因为 LoadingWindow 将无法正确显示,直到LoadingWindow.Show();之后的代码LoadingWindow.Show(); gets executed.被执行。

I have a custom Async ShowDialog method ShowDialogAsync();我有一个自定义的 Async Sh​​owDialog 方法ShowDialogAsync(); , but the problem is await will not reach till the AnotherForm.ShowDialog(); ,但问题是 await 直到AnotherForm.ShowDialog();才会到达AnotherForm.ShowDialog(); get completed.完成。

I tried:我试过了:

var LoadingTask = LoadingWindow.ShowDialogAsync();
Thread.Sleep(2000);     //Simulates slowness
//await AnotherForm.ShowDialogAsync();    //Not worked
//AnotherForm.ShowDialog();               //Not worked
//AnotherForm.Show();                     //Not Worked
LoadingWindow.Close();
await LoadingTask;

This can only be used with await for simple methods:这只能与 await 一起用于简单的方法:

var LoadingTask = LoadingWindow.ShowDialogAsync();
var data = await LoadDataAsync();
LoadingWindow.Close();
await LoadingTask;

//Sample simple method
private void LoadDataAsync()
{
        await Task.Delay(2000);
        return 10;
}

ShowDialogAsync: ShowDialogAsync:

public static async Task<DialogResult> ShowDialogAsync(this Form @this)
{
    await Task.Yield();
    if (@this.IsDisposed)
        return DialogResult.OK;
    return @this.ShowDialog();
}

As the author of the linked answer , I feel summoned :) I think I understand the problem you're running into.作为链接答案的作者,我感到被召唤:) 我想我理解您遇到的问题。 Try the following, see the comments inline:尝试以下操作,查看内联注释:

// on the main message loop of the UI thread
var LoadingTask = LoadingWindow.ShowDialogAsync();

// dialog isn't shown here yet, yield to the message loop
await Task.Yield();

// now ShowDialog has been called and the dialog is visible,
// we're now on the nested message loop run by ShowDialog
await Task.Run(() => 
{
  // on a thread pool thread, do the work here
  Thread.Sleep(2000);
});

// on the UI thread, still on the nested message loop of ShowDialog
// close the dialog
LoadingWindow.Close();

// still on the nested message loop, despite the window has closed
await LoadingTask;

// this is when ShowDialog method has returned,
// and we're back to the main message loop of the UI thread

Don't use Thread.Sleep or any other long-running synchronous code on the UI thread, even when experementing.不要在 UI 线程上使用Thread.Sleep或任何其他长时间运行的同步代码,即使是在实验中。 The dialog is shown asynchronously.该对话框是异步显示的。 Thread.Sleep blocks the message loop and the ShowDialog isn't getting a chance to execute when you expect it to. Thread.Sleep阻塞消息循环,并且ShowDialog没有机会在您期望的时候执行。

It helps to understand what Task.Yield actually does behind the sence in this case.在这种情况下,它有助于理解Task.YieldTask.Yield背后实际做了什么。 The continuation code after await Task.Yield() won't get magically executed until after some future iterations of the message loop. await Task.Yield()之后的继续代码直到消息循环的一些未来迭代之后才会神奇地执行。 And there will be no future iterations while you're making a blocking call on the UI thread.当您在 UI 线程上进行阻塞调用时,将不会有未来的迭代。 That's what the thread pool and Task.Run are for.这就是线程池和Task.Run的用途。

Otherwise, the continuation callback will be just sitting in the queue managed by WindowsFormsSynchronizationContext or DispatcherSynchronizationContext .否则,继续回调将位于由WindowsFormsSynchronizationContextDispatcherSynchronizationContext管理的队列中。

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

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