2016-03-31 86 views
2

我知道這個問題已經被問過很多次了,但是我找不到一個適合我的答案。試圖同步調用異步方法時出現死鎖

我正在寫一個Xamarin Forms應用程序。在Android項目中,我需要重寫此方法:

public override bool OnJsConfirm(WebView view, string url, string message, JsResult result) 

因此,不幸的是我無法使方法異步。

在這個方法我想稱之爲另一種:

public static Task<bool> DisplayAlert(string title, string message, string accept, string cancel) 
{ 
    var tcs = new TaskCompletionSource<bool>(); 

    Device.BeginInvokeOnMainThread(async() => 
    { 
     var result = await MainPage.DisplayAlert(title, message, accept, cancel); 
     tcs.SetResult(result); 
    }); 

    return tcs.Task; 
} 

MainPage.DisplayAlert()需要在UI線程這我的方法保證了調用。

我已經找過DisplayAlert從同步OnJsConfirm方法與這些變量:

//bool success = UI.DisplayAlert(title, message, ok, cancel).Result;        // hangs !!! 
//bool success = UI.DisplayAlert(title, message, ok, cancel).WaitAndUnwrapException();    // hangs !!! WaitAndUnwrapException is in Nito.AsyncEx.Synchronous 
//bool success = Nito.AsyncEx.AsyncContext.Run(() => UI.DisplayAlert(title, message, ok, cancel)); // hangs !!! 
//bool success = TaskEx.Run(() => UI.DisplayAlert(title, message, ok, cancel)).Result;    // hangs !!! 
//bool success = Task.Run(() => UI.DisplayAlert(title, message, ok, cancel)).Result;    // hangs !!! 
//bool success = Task.Run(async() => await UI.DisplayAlert(title, message, ok, cancel)).Result; // hangs !!! 
bool success = Task.Run(async() => await UI.DisplayAlert(title, message, ok, cancel).ConfigureAwait(false)).Result; // hangs !!! 

我把使用Nito.AsyncEx建議從this answer由斯蒂芬·克利裏對一個類似問題。

我也已經嘗試將.ConfigureAwait(false)添加到await MainPage.DisplayAlert(...),但這也不起作用。

當我設置一個斷點在await MainPage.DisplayAlert線,然後將其在所有,但最後兩個變體擊中,當我再按下F10,VS2015停止了與該調用堆棧: enter image description here

有沒有例外,雖然。該應用程序只是掛起。

有誰知道,我怎麼能調用我的異步方法?

+0

它看起來像您所呼叫DisplayAlert內DisplayAlert所以你將只保留調用它永遠因此,應用程序掛在黑暗中() –

+0

拍攝可能的工作'新的處理程序。郵政(新的Runnable(異步()= > // code));' –

回答

2

返回值OnJsConfirm僅表示,如果您將處理確認對話框。所以你需要返回true,並以異步方式完成其餘部分。如果您的DisplayAlert返回,您可以根據任務的結果調用JsResult上的Confim()Cancel()

public override bool OnJsConfirm(WebView view, string url, string message, JsResult result) 
{ 
    DisplayAlert("Really?", message, "OK", "Cancel").ContinueWith(t => { 
     if(t.Result) { 
      result.Confirm(); 
     } 
     else { 
      result.Cancel(); 
     } 
    }); 
    return true; 
} 


public static Task<bool> DisplayAlert(string title, string message, string accept, string cancel) 
{ 
    var tcs = new TaskCompletionSource<bool>(); 

    Device.BeginInvokeOnMainThread(async() => 
    { 
     var result = await MainPage.DisplayAlert(title, message, accept, cancel); 
     tcs.SetResult(result); 
    }); 

    return tcs.Task; 
}