2016-09-24 20 views
3

私は、Device.BeginInvokeOnMainThreadを使用してUIスレッドのUI要素を更新するルールに精通していますが、実際にはUIスレッドで実行する必要がある操作があります。仕事。Xamarin.Forms - 非同期アクション用のBeginInvokeOnMainThread

たとえば、XLabs.Forms.MvvmのPush/PopAsyncメソッドは、UIスレッドで呼び出されない限り、iOSでは誤って動作するようです。また、Acr.UserDialogsライブラリにトーストなどを表示するための別の例があります。

私は、非同期void lambdaを基本的に作成し、例外の場合にはデッドロックを作成するリスクがあることを知っています私はこれが起こることを望んでいない。

アクションを非同期としてマークすることを含まないUIスレッドで非同期操作を実行するための回避策はありますか?

答えて

5

アクションで例外を処理していることを確認してください。説明した問題は、が例外を処理していないときに発生します。以下は、メインスレッドから非同期メソッドを実行する非常に簡単な例です。

private void Test() 
{ 
    Device.BeginInvokeOnMainThread(SomeMethod); 
} 

private async void SomeMethod() 
{ 
    try 
    { 
     await SomeAsyncMethod(); 
    } 
    catch (Exception e) // handle whatever exceptions you expect 
    { 
     //Handle exceptions 
    } 
} 

private async Task SomeAsyncMethod() 
{ 
    await Navigation.PushModalAsync(new ContentPage()); 
} 
2

場合誰かにここにこれをドロップするには、メインスレッド上で実行する必要があるアクションの終了を待つしたい

public static class DeviceHelper 
{ 
    public static Task RunOnMainThreadAsync(Action action) 
    { 
     var tcs = new TaskCompletionSource<object>(); 
     Device.BeginInvokeOnMainThread(
      () => 
      { 
       try 
       { 
        action(); 
        tcs.SetResult(null); 
       } 
       catch (Exception e) 
       { 
        tcs.SetException(e); 
       } 
      }); 

     return tcs.Task; 
    } 

    public static Task RunOnMainThreadAsync(Task action) 
    { 
     var tcs = new TaskCompletionSource<object>(); 
     Device.BeginInvokeOnMainThread(
      async() => 
      { 
       try 
       { 
        await action; 
        tcs.SetResult(null); 
       } 
       catch (Exception e) 
       { 
        tcs.SetException(e); 
       } 
      }); 

     return tcs.Task; 
    } 
} 
関連する問題