在计时器回调中创建地图图标



我正在创建一个小型通用Windows应用程序。我想使用MapControl来呈现从互联网下载的一些数据。这些数据每分钟刷新一次,我想每次发生时更新 MapIcon 的位置。所以。。。加载地图后,我创建了一个每 60 秒运行一次的计时器,并使用 HttpWebRequest 下载数据,然后解析收到的 JSON,然后更新 MapControl 中显示的 MapIcon 的位置。

一切都应该正常工作,但是当我在计时器回调中调用新的 MapIcon() 时,我有一个例外:

newproject 中发生了类型为"System.Exception"的异常.exe但未在用户代码中处理

其他信息:应用程序调用了为不同线程封送的接口。(HRESULT的例外:0x8001010E(RPC_E_WRONG_THREAD))

我的计时器回调代码是:

    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);
                }
            }
        }
    }

请尝试使用调度程序。您需要在 UI 线程上添加 MapIcon 对象。

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

尽管Jean-Sébastien Dupuy的答案在技术上是正确的,但另一种选择是使用HttpClient而不是HttpWebRequest并使用await关键字来确保所有内容在正确的线程上自动运行。(还要确保您使用的是DispatcherTimer而不是其他类型的计时器)。

最新更新