Question

It's from Windows Phone project. I am trying to invoke few handlers, handler by handler to receive information about GPS / Reverse position. I wonder why it won't run correctly.

When I setup only 1 coordinate it's ok. I have message with Street etc. But when there is more coordinates my handler isn't invoke.

private async void SimulationResults()
        {
            done = new AutoResetEvent(true);
            Geolocator geolocator = new Geolocator();
            geolocator.DesiredAccuracy = PositionAccuracy.High;

            myCoordinate = new GeoCoordinate(51.751985, 19.426515);


            if (myMap.Layers.Count() > 0) myMap.Layers.Clear();

            mySimulation = new List<SimulationItem>();
            mySimulation = Simulation.SimulationProcess(myCoordinate, 120); // Odległość

            for(int i = 0; i<2; i++)
            {
                done.WaitOne();
                if (mySimulation.ElementAt(i).Id == 1 | mySimulation.ElementAt(i).Id == -1)
                {
                    // Oczekiwanie, ponieważ obiekt jest zasygnalizowany od razu wejdziemy
                    // do sekcji krytycznej
                    AddMapLayer(mySimulation.ElementAt(i).Coordinate, Colors.Yellow, false);

                    myReverseGeocodeQuery_1 = new ReverseGeocodeQuery();
                    myReverseGeocodeQuery_1.GeoCoordinate = mySimulation.ElementAt(i).Coordinate;
                    myReverseGeocodeQuery_1.QueryCompleted += ReverseGeocodeQuery_QueryCompleted_1;
                    // Sekcja krytyczna
                    done.Reset(); // Hey I'm working, wait!
                    myReverseGeocodeQuery_1.QueryAsync();

                }
            }
            MessageBox.Show("Skonczylem");
        }

        private void ReverseGeocodeQuery_QueryCompleted_1(object sender, QueryCompletedEventArgs<IList<MapLocation>> e)
        {
            done.Set();
            if (e.Error == null)
            {
                if (e.Result.Count > 0)
                {
                    MapAddress address = e.Result[0].Information.Address;
                    MessageBox.Show("Wykonano "+address.Street);

                }
            }
        } 
Was it helpful?

Solution

What's happening here is that you are blocking on your AutoResetEvent on the UI thread, but that's the same thread that the ReverseGeocodeQuery is trying to run on. Since it's blocked it can't run and it also can't invoke your callback.

A very quick fix that doesn't change your flow too much and assumes some sort of "on everything complete do X" requirement is below. I triggered the whole thing on a background thread with:

    new Thread(new ThreadStart(() =>
        {
            SimulationResults();
        })).Start();

Since all of the below is on a background thread I needed to add some Dispatcher.BeginInvoke() calls around anything that called into the UI thread, but this way the thread that is blocked is your background thread and not your UI thread.

    AutoResetEvent done;
    int remaining;

    private async void SimulationResults()
    {
        done = new AutoResetEvent(true);
        Geolocator geolocator = new Geolocator();
        geolocator.DesiredAccuracy = PositionAccuracy.High;

        var myCoordinate = new GeoCoordinate(51.751985, 19.426515);


        var mySimulation = new List<GeoCoordinate>()
        {
            new GeoCoordinate(51.751985, 19.426515),
            new GeoCoordinate(2, 2)
        };
        //mySimulation = Simulation.SimulationProcess(myCoordinate, 120); // Odległość

        remaining = mySimulation.Count;

        for (int i = 0; i < mySimulation.Count; i++)
        {
            done.WaitOne();
            //if (mySimulation.ElementAt(i).Id == 1 | mySimulation.ElementAt(i).Id == -1)
            //{
                // Oczekiwanie, ponieważ obiekt jest zasygnalizowany od razu wejdziemy
                // do sekcji krytycznej
                //AddMapLayer(mySimulation.ElementAt(i).Coordinate, Colors.Yellow, false);

            var tempI = i;

            Dispatcher.BeginInvoke(() =>
            {

                var myReverseGeocodeQuery_1 = new ReverseGeocodeQuery();
                myReverseGeocodeQuery_1.GeoCoordinate = mySimulation.ElementAt(tempI);
                myReverseGeocodeQuery_1.QueryCompleted += ReverseGeocodeQuery_QueryCompleted_1;
                // Sekcja krytyczna
                done.Reset(); // Hey I'm working, wait!
                myReverseGeocodeQuery_1.QueryAsync();
            });

            //}
        }

    }

    private void ReverseGeocodeQuery_QueryCompleted_1(object sender, QueryCompletedEventArgs<IList<MapLocation>> e)
    {
        done.Set();

        remaining--;

        if (e.Error == null)
        {
            if (e.Result.Count > 0)
            {
                MapAddress address = e.Result[0].Information.Address;
                Dispatcher.BeginInvoke(() =>
                {
                    MessageBox.Show("Wykonano " + address.Street);
                });

            }
        }

        if (remaining == 0)
        {
            // Do all done code
            Dispatcher.BeginInvoke(() =>
            {
                MessageBox.Show("Skonczylem");
            });
        }
    } 

Alternatively you could also make this a proper async method that awaits on different events to progress.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top