2013-03-20 1 views
1

약간 혼란스러워.TimerCallback 함수에서 UI 스레드 업데이트 Windows Phone 8

맵에 넣을 지오 포인트가 포함 된 매 10 초마다 발생하는 TimerCallback이 있습니다. 타이머 콜백 함수 내에서지도에 추가하려고하지만 다른 스레드에 있기 때문에이 작업을 수행 할 수 없습니다. 나는 다음과 같은 오류가 나타날 :

유형 'System.IO.FileNotFoundException'형식의 예외

는 mscorlib.ni.dll 발생 및 관리/네이티브 경계하기 전에 처리되지 않았습니다.

'System.UnauthorizedAccessException' 내가이 문제를 회피 할 수 있습니다 얼마나

System.Windows.ni.dll

에서 발생 유형의 첫 번째 예외? NotifyCollectionChanged 리스너를 추가한다고 생각했지만, 여전히 동일한 문제가 발생했습니다. 코드는 아래와 같습니다.

public void obtainJSON(Object stateInfo) 
{  
    Dispatcher.BeginInvoke(() => { 
     string url = "http://xxx.xxx.xxx" + stateInfo.ToString(); 
     var client = new WebClient(); 
     client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(Decrypt); 
     client.DownloadStringAsync(new Uri(url)); 
    });  
} 

이 모든 것을 (모두 웹을 만드는 것을 의미합니다

private ObservableCollection<Bus> _busList; 
    private Timer _timer = null; 
    public ItemViewModel route; 

    public ObservableCollection<Bus> BusList 
    { 
     get { return _busList; } 
     set { _busList = value; } 
    } 
    //public LocationManager locMan = LocationManager.Instance; 
    // Constructor 
    public DetailsPage() 
    { 
     InitializeComponent(); 

     // Sample code to localize the ApplicationBar 
     //BuildLocalizedApplicationBar(); 
    } 

    // When page is navigated to set data context to selected item in list 
    protected override void OnNavigatedTo(NavigationEventArgs e) 
    { 
     route = null; 
     if (DataContext == null) 
     { 
      string selectedIndex = ""; 
      if (NavigationContext.QueryString.TryGetValue("selectedItem", out selectedIndex)) 
      { 
       int index = int.Parse(selectedIndex); 
       DataContext = App.ViewModel.Items[index]; 
       route = App.ViewModel.Items[index]; 
       if (_timer == null) 
       { 
        TimerCallback tcb = obtainJSON; 
        _timer = new Timer(tcb, route.RouteID, 0, 10000); 
       } 
       else 
       { 
        _timer.Change(0, 10000); 
       } 
       if (BusList == null) 
       { 
        BusList = new ObservableCollection<Bus>(); 
       } 
       else 
       { 
        BusList.Clear(); 
       } 
       BusList.CollectionChanged += HandleBusAdded; 
      } 
     } 
    } 

    private void HandleBusAdded(object sender, NotifyCollectionChangedEventArgs e) 
    { 
     if (e.Action == NotifyCollectionChangedAction.Reset) 
     { 
      Debug.WriteLine("Everything was cleared"); 
     } 
     else 
     { 
      foreach (Bus item in e.NewItems) 
      { 
       Debug.WriteLine(item.vehicleID); 
       Polygon polygon = new Polygon(); 
       polygon.Points.Add(new Point(0, 0)); 
       polygon.Points.Add(new Point(0, 75)); 
       polygon.Points.Add(new Point(25, 0)); 
       polygon.Fill = new SolidColorBrush(Colors.Blue); 

       // Create a MapOverlay and add marker 
       MapOverlay overlay = new MapOverlay(); 
       overlay.Content = polygon; 
       overlay.GeoCoordinate = new GeoCoordinate(item.lat, item.lng); 
       overlay.PositionOrigin = new Point(0.0, 1.0); 
       MapLayer mapLayer = new MapLayer(); 
       mapLayer.Add(overlay); 
       //mapView.Layers.Add(mapLayer); 

       this.Dispatcher.BeginInvoke(() => 
       { 
        mapView.Layers.Add(mapLayer); 
       }); 
      } 
     } 

    } 

    public void obtainJSON(Object stateInfo) 
    { 

     string url = "http://xxx.xxx.xxx" + stateInfo.ToString(); 
     var client = new WebClient(); 
     client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(Decrypt); 
     client.DownloadStringAsync(new Uri(url)); 
    } 

    public void Decrypt(Object sender, DownloadStringCompletedEventArgs e) 
    { 
     if (BusList.Count > 0) 
     { 
      BusList.Clear(); 
     } 
     if (!e.Cancelled && e.Error == null) 
     { 
      var temp = new List<string>(); 
      string[] buses = e.Result.Split('\n'); 
      foreach (string bus in buses) 
      { 
       if (!string.IsNullOrWhiteSpace(bus) && !string.IsNullOrEmpty(bus)) 
       { 
        temp.Add(bus); 
       } 
      } 
      foreach (string item in temp) 
      { 
       string[] busInfo = item.Split(','); 
       Bus newBus = new Bus(busInfo[0], busInfo[1], busInfo[2]); 
       BusList.Add(newBus); 

      } 

      // This is where I initially tried 
      /*Polygon polygon = new Polygon(); 
      polygon.Points.Add(new Point(0, 0)); 
      polygon.Points.Add(new Point(0, 75)); 
      polygon.Points.Add(new Point(25, 0)); 
      polygon.Fill = new SolidColorBrush(Colors.Blue); 

      // Enable marker to be tapped for location information 
      // polygon.Tag = new GeoCoordinate(BusList[0].lat, BusList[0].lng); 

      // Create a MapOverlay and add marker 
      MapOverlay overlay = new MapOverlay(); 
      overlay.Content = polygon; 
      overlay.GeoCoordinate = new GeoCoordinate(BusList[0].lat, BusList[0].lng); 
      overlay.PositionOrigin = new Point(0.0, 1.0); 
      MapLayer mapLayer = new MapLayer(); 
      mapLayer.Add(overlay); 

      this.Dispatcher.BeginInvoke(() => 
      { 
       mapView.Layers.Add(mapLayer); 
      });*/ 
      Debug.WriteLine("Present buses " + BusList[0].vehicleID + ", " + BusList[1].vehicleID); 
     } 
    } 
} 

답변

3

가장 간단한 것은 UI 스레드에 다시 전달되는 익명 함수에 obtainJSON 방법에 일어나는 포장하는 것 요청을 처리하고 응답을 처리하면 (WebClient은 호출 된 스레드에서 콜백을 실행 함) UI 스레드에서 발생하므로 다른 스레드에서 UI 스레드에 바인딩 된 객체를 업데이트하지 않습니다.

스레딩이 아닌 DispatcherTimer을 사용해 볼 수도 있습니다.

또한 요청이 10 초 이상 시간이 초과되고 요청이 여러 번 실행될 수있는 열악한 네트워크 조건도 처리해야합니다. 이는 여러 가지 요청을 실행하는 데 문제가 될 수 있습니다.