0
votes

I'm creating a small universal windows application. I'd like to use MapControl to present some data downloaded from the Internet. This data refreshes every minute and I want to update MapIcons positions everytime that it happens. So... After loading a map, I create a Timer that runs every 60 seconds and downloads the data using HttpWebRequest, then parses received JSON and then updates the positions of MapIcons displayed in MapControl.

Everything should work fine, however when I call new MapIcon() in Timer callback I have an exception:

An exception of type 'System.Exception' occurred in newproject.exe but was not handled in user code

Additional information: The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))

My Timer callback code is:

    private async void OnTimerTick(Object stateInfo)
    {
        var TramDataList = await Loader.LoadData();
        updateMarkers(TramDataList);
    }

    private void updateMarkers(List<TramData> tramList)
    {
        lock (TramMarkerDict)
        {
            foreach (var tramData in tramList)
            {
                if (!TramDataDict.ContainsKey(tramData.Id))
                {
                    TramDataDict.Remove(tramData.Id);
                    TramMarkerDict.Remove(tramData.Id);
                }
            }

            foreach (var tramData in tramList)
            {
                TramData tmp = null;
                var exists = TramDataDict.TryGetValue(tramData.Id, out tmp);
                if (exists)
                    tmp.update(tramData);
                else
                    TramDataDict.Add(tramData.Id, tramData);
            }

            foreach (var tramData in TramDataDict.Values)
            {
                MapIcon mapIcon = null;
                var geopoint = new Windows.Devices.Geolocation.Geopoint(
                    new Windows.Devices.Geolocation.BasicGeoposition { Latitude = tramData.Lat, Longitude = tramData.Lng });
                var exists = TramMarkerDict.TryGetValue(tramData.Id, out mapIcon);
                if (exists)
                    mapIcon.Location = geopoint;
                else
                {
                    mapIcon = new MapIcon { Location = geopoint, Title = tramData.FirstLine, NormalizedAnchorPoint = new Point(0.5, 1) };
                    TramMarkerDict.Add(tramData.Id, mapIcon);
                }
            }
        }
    }
2

2 Answers

1
votes

Please try using a Dispatcher. You need to add MapIcon objects on the UI Thread.

    private async void MainPage_Loaded(object sender, RoutedEventArgs e)
    {
        await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => 
        {
            // Your Code
        });
    }
0
votes

Although Jean-Sébastien Dupuy's answer is technically correct, another option is to use HttpClient instead of HttpWebRequest and use the await keyword to ensure everything automatically runs on the correct thread. (Also make sure you're using a DispatcherTimer and not some other kind of timer).