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