【问题标题】:MapIcon creation in Timer callback在 Timer 回调中创建 MapIcon
【发布时间】:2016-04-24 15:10:04
【问题描述】:

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

一切正常,但是当我在 Timer 回调中调用 new MapIcon() 时出现异常:

newproject.exe 中出现“System.Exception”类型的异常,但未在用户代码中处理

附加信息:应用程序调用了为不同线程编组的接口。 (来自 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);
                }
            }
        }
    }

【问题讨论】:

    标签: c# multithreading timer win-universal-app


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      虽然Jean-Sébastien Dupuy's answer 在技术上是正确的,但另一种选择是使用HttpClient 而不是HttpWebRequest 并使用await 关键字来确保一切都自动在正确的线程上运行。 (还要确保您使用的是 DispatcherTimer 而不是其他类型的计时器)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多