簡體   English   中英

調用 ShowDialog() 后繼續執行代碼

[英]Continue code execution after calling ShowDialog()

我試圖在 else 代碼在后台繼續執行時打開一個加載窗口,並在需要時關閉它(無線程)。

像這樣的東西:

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

我不能只使用LoadingWindow.Show(); 繼續執行,因為 LoadingWindow 將無法正確顯示,直到LoadingWindow.Show();之后的代碼LoadingWindow.Show(); 被執行。

我有一個自定義的 Async Sh​​owDialog 方法ShowDialogAsync(); ,但問題是 await 直到AnotherForm.ShowDialog();才會到達AnotherForm.ShowDialog(); 完成。

我試過了:

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;

這只能與 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:

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

作為鏈接答案的作者,我感到被召喚:) 我想我理解您遇到的問題。 嘗試以下操作,查看內聯注釋:

// 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

不要在 UI 線程上使用Thread.Sleep或任何其他長時間運行的同步代碼,即使是在實驗中。 該對話框是異步顯示的。 Thread.Sleep阻塞消息循環,並且ShowDialog沒有機會在您期望的時候執行。

在這種情況下,它有助於理解Task.YieldTask.Yield背后實際做了什么。 await Task.Yield()之后的繼續代碼直到消息循環的一些未來迭代之后才會神奇地執行。 當您在 UI 線程上進行阻塞調用時,將不會有未來的迭代。 這就是線程池和Task.Run的用途。

否則,繼續回調將位於由WindowsFormsSynchronizationContextDispatcherSynchronizationContext管理的隊列中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM