2013-01-18 1 views
0

내 앱 사용자 중 일부가 추적 측이 작동하지 않는다고 불평하고 있습니다. 앱이 GeoCoordinateWatcher를 시작하고 현재 위치를 얻으려고하는 동안 화면 상단에 GPS 아이콘이 깜박입니다. 이 작업이 끝나면 아이콘이 깜박임을 멈추고 Ready (준비)라는 메시지가 나타납니다. 사용자는 이러한 일이 발생한다고보고하지만 속도와 같은 화면의 항목은 절대 업데이트되지 않습니다. 앱이 추적 한 위치를 저장하면 아무 것도 없습니다.Windows 전화 앱에서 위치 추적 관련 문제가 발생했습니다.

다음은 추적 부분 코드입니다. 페이지로드 이벤트에서 그것은

/// <summary> 
    /// Starts tracking the user 
    /// </summary> 
    private void StartTracking() 
    { 
     var app = (Application.Current as App); 

     // check to see if tracking is enabled by the user      
     if (app.LocationTrackingIsEnabled) 
     {    
       (new Thread(() => 
       { 
        // Create the GeoWatcher 
        var watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High) { MovementThreshold = 1 }; 

        // Check to see if we have permission to use the location services of the phone 
        if (watcher.Permission == GeoPositionPermission.Granted) 
        { 
         watcher.StatusChanged += new EventHandler<GeoPositionStatusChangedEventArgs>(watcher_StatusChanged); 

         var status = Observable.FromEvent<GeoPositionStatusChangedEventArgs>(watcher, "StatusChanged"); 
         var readys = status.Where(o => o.EventArgs.Status == GeoPositionStatus.Ready); 
         var notReadys = status.Where(o => o.EventArgs.Status != GeoPositionStatus.Ready); 
         var readyPos = from r in readys 
             from i in Observable.Interval(TimeSpan.FromSeconds(LocationTrackInterval)) 
             .TakeUntil(notReadys) 
             where (DateTime.Now - watcher.Position.Timestamp.DateTime) < TimeSpan.FromSeconds(12) 
             select watcher.Position; 

         LocationSubscribe = readyPos.Subscribe(loc => 
         { 
          if (!HasPaused) 
          { 
           this.Dispatcher.BeginInvoke(new Action(() => 
           { 
            // Get current speed (meters per second); 
            if (!double.IsNaN(loc.Location.Speed)) 
             app.CurrentPos.CurrentSpeed = Math.Round(loc.Location.Speed, 2); 
            else 
             app.CurrentPos.CurrentSpeed = 0; 

            // Calculate distance 
            if (RunLocations.Count > 0) 
             app.CurrentPos.DistanceMeters += Math.Round(new GeoCoordinate(RunLocations[RunLocations.Count - 1].Latitude, 
              GPSLocations[GPSLocations.Count - 1].Longitude).GetDistanceTo(loc.Location), 2); 

            // Add Location 
            GPSLocations.Add(new GPSLocation() 
            { 
             Latitude = loc.Location.Latitude, 
             Longitude = loc.Location.Longitude, 
             Altitude = loc.Location.Altitude, 
             Speed = app.CurrentRun.CurrentSpeed 
            }); 

            // Get the average speed 
            app.CurrentPos.AverageSpeed = Math.Round((from r in GPSLocations 
                       select r.Speed).Average(), 2); 


            // Set last position for use later 
            Lastlocation = loc.Location; 
           })); 
          } 
         }); 

         // Try and start the watcher 
         if (!watcher.TryStart(false, TimeSpan.FromSeconds(5))) 
         { 
          this.Dispatcher.BeginInvoke(new Action(() => 
          { 
           MessageBox.Show("There was an error trying to get your location. Tracking is not possible."); 
          })); 
         } 
        } 
        else 
        { 
         sbGpsFlash.Stop(); // stop the flashing gps symbol 
         gpsStatus.Text = "Denied"; 
        } 

       })).Start();     
     } 
     else 
     { 
      sbGpsFlash.Stop(); // stop the flashing gps symbol 
      gpsStatus.Text = "Disabled"; 
     } 
    } 

void watcher_StatusChanged(object sender, GeoPositionStatusChangedEventArgs e) 
    { 
     this.Dispatcher.BeginInvoke(new Action(() => 
     { 
      gpsStatus.Text = e.Status.ToString(); 

      switch (e.Status) 
      { 
       case GeoPositionStatus.Initializing: 
        gpsStatus.Text = "Locating..."; 
        break; 
       case GeoPositionStatus.Disabled: 
        gpsStatus.Text = "Disabled"; 
        break; 
       case GeoPositionStatus.NoData: 
        gpsStatus.Text = "No Data"; 
        break; 
       case GeoPositionStatus.Ready: 
        gpsStatus.Text = "Ready"; 
        break;          
      } 

      sbGpsFlash.Stop(); 
     })); 
    } 

이 사람이 문제가 발생할 수 있습니다 코드에 문제를 볼 수

다음 호출?

답변

0

메인 스레드에서 geocoordinatewatcher를 만듭니다.

+0

watcher = new GeoCoordinateWatcher (GeoPositionAccuracy.High)를 주 스레드로 이동하십시오. 왜 그런지 물어봐도 될까요? 단지 나의 이해를 위해 :-) – Gaz83

+0

단지 직감. 주된 스레드가 아닌 다른 스레드에서 GCW를 작성하면 다른 디스패처가 생겨 모든 종류의 스레드 간 액세스 문제가 발생합니다. 근본적으로 작업자 스레드가 주 스레드에 의해 생성 된 위젯을 만질 수없는 일반적인 상황과 정확히 반대되는 상황을 만듭니다. 게다가 GCW를 사용해 보았을 때 주 스레드에서 생성 했으므로 번거 로움이 없습니다. –

0

측면 설명.

코드는 작지만 읽을 수는 없습니다.

주 스레드에 좌표 감시자를 만들 필요가 없습니다.

위치 이벤트에만 서브 스크립 션하지만 위치 챔딩 이벤트에는 포함시키지 않는 것이 궁금합니다. 그러나 이것은 귀하의 논리이며, 귀하가 괜찮 으면 괜찮습니다.

점은 UI에서 표시 할 데이터입니다. UI 컨트롤을 만든 스레드의 UI 컨트롤에만 할당 할 수 있습니다. 일반적으로 이것은 스레드가 "기본"스레드라고합니다. 나는 이것이 왜 메인 스레드인지는 모르겠다. 실제로 UI 스레드라고 부릅니다.

그래서 UI 컨트롤이 만들어진 UI 스레드에서 데이터를 전달해야합니다. UI 스레드에서 감시자를 시작하거나 UI 스레드의 Dispatcher를 사용하여 데이터를 전달하고 UI 컨트롤에 데이터를 할당하십시오.

관련 문제