2016-08-22 103 views
1

我有以下幾種方法:C#等待對話框主線程返回

public override bool SyncNavigationMethod() 
{ 
    AsyncShowDialog().Wait(); 
    return true; 
} 

public Task AsyncShowDialog() 
{ 
    //code to show dialog and process user input from the dialog. 
} 

什麼情況是,應用進入一個僵局時SyncNavigationMethod被調用。

我的猜測是它運行在等待AsyncShowDialog完成的MainThread上,並且顯示的對話框無法調用它的回調,因爲它是調用它的MainThread。因此,主線程等待自己,這是一個僵局。

的更多信息:

  • 運行 - UWP。
  • 設備:手機(如上所述)桌面(應用程序在顯示對話框之前凍結)。
  • 我試過在AsyncShowDialog上使用.Wait()\ .Result。
  • 我試圖在調用AsyncShowDialog以在AsyncShowDialog運行時阻止進度代碼之後使用ManualResetEvent。

我是否懷疑deadLock?

如何在沒有此死鎖的情況下從SyncNavigationMethod調用AsyncShowDialog?

感謝。

+0

對於UI線程,你需要'Task.WhenAll'或'Await','Task.Wait/Task。WaitAll'將導致死鎖 –

回答

2

我會斯蒂芬·克利裏,這說明,異步調用的同步阻塞如何導致死鎖,這就是真正的爲除Console所有系統,它不具有用戶界面最好的博客post的一個開始上下文線程:

現在關於你的代碼,並指出:

因此,主線程等待本身,這是一個僵局。

是的是的話,你已經正確地理解這是一個僵局,由於Mainthread阻塞本身

Wait, Result and ManualResetEvent,他們都同步阻止異步代碼,從而相同的結果

可能的解決方案:

如果調用是Rest APIweb based call,則將所有東西都做成Async,並且IIS將確保它可以返回執行後的頂級Async-Await,某些興象:

public async override Task<bool> SyncNavigationMethod() 
{ 
    await AsyncShowDialog(); 
    return true; 
} 

public async Task AsyncShowDialog() 
{ 
    await SomeOperation(); 
} 

Task<bool>返回值會自動解包

其他選項:

如果你不能使SyncNavigationMethod() Async,那就試試這個:

public override bool SyncNavigationMethod() 
    { 
     List<Task> taskList = new List<Task>(); 
     taskList.Add(AsyncShowDialog()); 
     Task.WhenAll(taskList.ToArray()); 
     return true; 
    } 

    public async Task AsyncShowDialog() 
    { 
     await SomeOperation(); 
    } 
+1

'Task.WhenAll(....)'返回等待接收到的所有任務的任務。所以,我將不得不等待這個任務。 通過這樣做,我只是用另一個任務包裝了'AsyncShowDialog()',它沒有幫助。 仍然是你爲你的時間。 昨天我改變了基礎設施,以支持'公共異步覆蓋任務 SyncNavigationMethod()'作爲你的第一個建議和我試圖避免的。 –

+0

你也可以嘗試'ConfigureAwait(false).GetAwaiter()。GetResult()',但是'ConfigureAwait',需要一直用到最頂端的調用。你不需要使用頂級方法'Async' –