简体   繁体   English

在计时器回调中创建MapIcon

[英]MapIcon creation in Timer callback

I'm creating a small universal windows application. 我正在创建一个小的通用Windows应用程序。 I'd like to use MapControl to present some data downloaded from the Internet. 我想使用MapControl呈现一些从Internet下载的数据。 This data refreshes every minute and I want to update MapIcons positions everytime that it happens. 该数据每分钟刷新一次,我希望每次发生时都更新MapIcons位置。 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. 所以...加载地图后,我创建一个Timer,每60秒运行一次,并使用HttpWebRequest下载数据,然后解析接收到的JSON,然后更新MapControl中显示的MapIcons的位置。

Everything should work fine, however when I call new MapIcon() in Timer callback I have an exception: 一切都应该正常工作,但是当我在Timer回调中调用new MapIcon()时,我有一个异常:

An exception of type 'System.Exception' occurred in newproject.exe but was not handled in user code newproject.exe中发生类型'System.Exception'的异常,但未在用户代码中处理

Additional information: The application called an interface that was marshalled for a different thread. 附加信息:该应用程序称为接口,该接口被编组用于其他线程。 (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD)) (来自HRESULT的异常:0x8001010E(RPC_E_WRONG_THREAD))

My Timer callback code is: 我的Timer回调代码是:

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

Please try using a Dispatcher. 请尝试使用分派器。 You need to add MapIcon objects on the UI Thread. 您需要在UI线程上添加MapIcon对象。

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

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. 尽管Jean-SébastienDupuy的回答在技​​术上是正确的,但另一个选择是使用HttpClient而不是HttpWebRequest并使用await关键字来确保所有内容都自动在正确的线程上运行。 (Also make sure you're using a DispatcherTimer and not some other kind of timer). (还要确保您使用的是DispatcherTimer而不是其他某种计时器)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM