2016-11-03 21 views
2

プロジェクトを単純化した後、問題が実際に非同期マーシャリングの結果であることがわかりました。NEW TITLE - アプリケーションが別のスレッド用にマーシャリングされたインターフェイスを呼び出しました

UPDATE:私はコードをより簡単にして、何が起こっていたのか把握しようとしました。 Observableコレクションに新しいスレッド(非同期メソッド)が設定されています。私は

async void LoadAllData(object sender, EventArgs e) 
    { 

     if (sender != null) 
     { 
      App.GeoLocationComplete -= LoadAllData; 
     } 
await ViewModelObjects.NearbyLocations.LoadLocationData(); 
lvPlaces.ItemsSource = ViewModelObjects.NearbyLocations.GBSLocationDetails; 
} 

データロード方法の定義の下に見られるようなのObservableCollectionがロードされた後にのItemsSourceの割り当てを移動しようとしたことは、以下である:私はこのコードを実行すると

public async Task LoadLocationData() 
    {....} 

Iを得ます次のエラーが発生しました:

アプリケーションは、別のスレッド用にマーシャリングされたインターフェイスを呼び出しました。 (HRESULTからの例外:0x8001010E(RPC_E_WRONG_THREAD))

私はエラーの原因を知っています(データはUIスレッド以外のスレッドに読み込まれました)が、どのように修正するのか分かりません。提案?

更新日:私は問題の根本原因を特定したが、修正方法を理解していないと思う。私は以下のようにコードを単純化することから始めました。

public nearbyplaces() 
    { 
     InitializeComponent(); 
     NavigationPage.SetHasNavigationBar(this, false); 
     LoadAllData(null, null); 
    } 

    void LoadAllData(object sender, EventArgs e) 
    { 

     lobj_Places = new ObservableCollection<GBSLocationDetail>() 
     { 
      new GBSLocationDetail() 
      { 
       Title = "Location 1", 
       Distance = "20 Miles", 
       AddInfo = "Something Else", 
       AttributesTexts="Gay, Bar, Dance" 
      } 
     }; 

     lvPlaces.ItemsSource = lobj_Places; 

    } 

私が必要とするのは、デバイスからGPS位置を取得した後にLoadAllDataメソッドを呼び出す必要があることです。だから私のApp.XAML.csに私は、次のデリゲートイベントが宣言している:

public static Plugin.Geolocator.Abstractions.IGeolocator gobj_RealGeoCoordinator; 
    public static event GeoLocationCompleteEventHandler GeoLocationComplete; 
    public static bool gb_WaitingForLocation = true; 

私は戻って、デバイスから位置を取得したら、その後、私はイベントを次のコードを呼び出しています:

private async void ProcessStartupandResume() 
    { 

     if (gobj_RealGeoCoordinator == null) 
     { 
      gobj_RealGeoCoordinator = CrossGeolocator.Current; 

      ViewModelObjects.AppSettings.CanAccessLocation = App.gobj_RealGeoCoordinator.IsGeolocationEnabled; 

      if (!ViewModelObjects.AppSettings.CanAccessLocation) 
      { 
       await MainPage.DisplayAlert(ResourceStrings.GetValue("NoLocationServicesTitle"), ResourceStrings.GetValue("NoLocationServicesMessage"), ResourceStrings.GetValue("OKButtonText")); 
      } 

      //Only add the events if the object has to be created. 
      gobj_RealGeoCoordinator.PositionChanged += gobj_RealGeoCoordinator_PositionChanged; 

      gobj_RealGeoCoordinator.PositionError += (sender, e) => 
      { 
       ProcessException(new Exception(e.Error.ToString())); 
      }; 
     } 

     //Set this to null to trigger the first check 
     ib_GPSReenabled = null; 

     if (gobj_RealGeoCoordinator.IsListening) 
      await gobj_RealGeoCoordinator.StopListeningAsync(); 

     gobj_RealGeoCoordinator.DesiredAccuracy = 50; 

     await gobj_RealGeoCoordinator.StartListeningAsync(10000, 20); 

    } 

    private static void gobj_RealGeoCoordinator_PositionChanged(object sender, PositionEventArgs e) 
    { 
     var pos = e.Position; 
     ViewModelObjects.AppSettings.Latitude = pos.Latitude; 
     ViewModelObjects.AppSettings.Longitude = pos.Longitude; 

     if (gb_WaitingForLocation) 
     { 
      gb_WaitingForLocation = false; 
      GeoLocationComplete?.Invoke(new object() , null); 
     } 
    } 

その後私のページでは、以下に示すように、LoadAllDataメソッドを使用してGeoLocationCompleteイベントを購読します。ローカルオブジェクトを使用して、イベントの結果として実行されるときにコード内のListViewのItemsSourceを設定しようとしても、エラーが発生します。イベントを購読している下記のコードをご覧ください:

public nearbyplaces() 
    { 
     InitializeComponent(); 
     NavigationPage.SetHasNavigationBar(this, false); 

     if (App.gb_WaitingForLocation) 
      App.GeoLocationComplete += LoadAllData; 
     else 
      LoadAllData(null, null); 
    } 

これを修正する方法についてのご意見はありますか?

+0

データをロードするときに、ObservableCollectionの既存のインスタンスにアイテムを追加したり、新しいインスタンスを作成したりしていますか?また、複雑なネストされたグリッドをコメントアウトし、バインディングを使用してViewCellに単一のラベルを配置するだけで、これを簡単にデバッグできます。 – Jason

+0

クラスコンストラクタでコレクションを初期化します。 public VM_NearbyLocations() { これです。GBSLocationDetails =新しいObservableCollection (); }そして私はWebAPIの結果からアイテムをコレクションをロード this.GBSLocationDetails = JsonConvert.DeserializeObject <のObservableCollection >(lobj_PlacesResponse.Content.ReadAsStringAsyncを待ちます())。 明日の簡略化されたアプローチを試し、結果をお知らせします。 –

+0

リストがバインドされているコレクションを新しいインスタンスに置き換えます。それはあなたがそれを意図した通りに働かない(私は思う)。 – Jason

答えて

0

これでわかりました。私は、メインスレッドでイベントを呼び出すために必要な、私は次のコードでそれをした:

 Device.BeginInvokeOnMainThread(() => 
      { 
       GeoLocationComplete?.Invoke(new object(), null); 
      }); 

このコードを挿入した後、エラーが消えていました。コードを単に

GeoLocationComplete?.Invoke(new object(), null); 

に変更すると、再びエラーが発生します。私はこれが私の問題を解決したと信じています。これが他の人に役立つことを願っています:)

関連する問題