i am using Gmap.net library to plot markers at a particular let-long coming after calculation made by triangulation algo on google maps,when i worked for two markers its works fine but when i tries to plot 5 markers its is showing me exception
An unhandled exception of type 'System.InvalidOperationException' occurred in mscorlib.dll
Additional information: Collection was modified; enumeration operation may not execute.
what i am doing ,i have created 5 threads for five markers ,which are plotting on the map.
- while markers are getting plotting ,if i do lots of zoom in zoom out it show exception.
- while plotting i move the map again it show exception.
i am unable to figure out why it is happening.even it is not showing me any line no. here is the snapshot of error. please help. EDIT: here is the code to plot on map includes adding markers and routes ,i have use same function for all 5 markers with different marker and routes name
void plot5(double temp_lat5, double temp_long5, string temp_date5, string temp_time5, string temp_bty_value5)
{
try
{
//GMapMarker marker5 = new GMarkerGoogle(new PointLatLng(temp_lat5, temp_long5), GMarkerGoogleType.lightblue);
GMapMarker marker5 = new GMarkerGoogle(new PointLatLng(temp_lat5, temp_long5), new Bitmap(Properties.Resources.image12));
gmap.Overlays.Add(markers5); // overlay added
Thread.Sleep(100);
markers5.Markers.Add(marker5); //marker added
marker5.ToolTipText = "AT CARD 05" + "\n" + "HIGH PRIORITY" + "\n" + temp_date5 + "\n" + temp_time5 + "\n" + temp_bty_value5 + "%"; //text to be displayed on the marker
// text properties
marker5.ToolTip.Fill = Brushes.Bisque;
marker5.ToolTip.Foreground = Brushes.White;
marker5.ToolTip.Stroke = Pens.Black;
marker5.ToolTip.TextPadding = new Size(20, 20);
if (count5 != 0)
{
List<PointLatLng> points5 = new List<PointLatLng>();
points5.Add(new PointLatLng(temp_lat5, temp_long5));
points5.Add(new PointLatLng(lat5, long5));
GMapRoute route5 = new GMapRoute(points5, "walk05");
route5.Stroke = new Pen(Color.Aquamarine, 3);
gmap.Overlays.Add(routes5); // first overlays then routes or markers
routes5.Routes.Add(route5);
}
count5++;
lat5 = temp_lat5;
long5 = temp_long5;
}
catch (Exception hy)
{ MessageBox.Show(hy.ToString()); }
that's how m calling the different threads /tasks(tried with both)
private void button1_Click(object sender, EventArgs e)// Creating and startting threads for 5 diffrent at cards
{
try
{
if (m_parentform.update_flag_data == 1)
{
if (list_at.Count != 0)
{
for (int y = 0; y < list_at.Count; y++)
{
for (int x = 0; x < m_parentform.at_cards_serials.Count; x++)
{
if (list_at[y] == m_parentform.at_cards_serials[x])
{
try
{
int index = m_parentform.at_cards_serials.IndexOf(m_parentform.at_cards_serials[x]);
switch (index)
{
case 0:
{
Task lat_longthread1 = new Task(new System.Action(custom01));
lat_longthread1.Start();
// await lat_longthread1;
// Thread lat_longthread1 = new Thread(new ThreadStart(custom01));
// lat_longthread1.Start();
break;
}
case 1:
{
Task lat_longthread2 = new Task(new System.Action(custom02));
lat_longthread2.Start();
// await lat_longthread2;
//Thread lat_longthread2 = new Thread(new ThreadStart(custom02));
//lat_longthread2.Start();
break;
}
case 2:
{
Task lat_longthread3 = new Task(new System.Action(custom03));
lat_longthread3.Start();
// await lat_longthread3;
//Thread lat_longthread3 = new Thread(new ThreadStart(custom03));
//lat_longthread3.Start();
break;
}
case 3:
{
Task lat_longthread4 = new Task(new System.Action(custom04));
lat_longthread4.Start();
// await lat_longthread4;
//Thread lat_longthread4 = new Thread(new ThreadStart(custom04));
//lat_longthread4.Start();
break;
}
case 4:
{
Task lat_longthread5 = new Task(new System.Action(custom05));
lat_longthread5.Start();
// await lat_longthread5;
//Thread lat_longthread5 = new Thread(new ThreadStart(custom05));
//lat_longthread5.Start();
break;
}
}
}
catch (Exception ty)
{ MessageBox.Show(ty.ToString()); }
}
}
}
}
else
{ MessageBox.Show("select at cards to plot"); }
}
else
{ MessageBox.Show("flag is not updated"); }
}
catch (Exception jo)
{ MessageBox.Show(jo.ToString()); }
CHANGES:following is the change i made ,added the plot function(described above),for all 5 markers in critical section ,still issue is same.
void marker_selection(int plot_no)
{
mut2.WaitOne();
int marker_no = plot_no;
switch (marker_no)
{
case 1:
{
plot(one1, two1, date[0], time[0], bty[0]); // not sending bty part 2 which indicates milli volt value
break;
}
case 2:
{
plot2(one2, two2, date2[0], time2[0], bty2[0]); // sending only part one of bty
break;
}
case 3:
{
plot3(one3, two3, date3[0], time3[0], bty3[0]); // sending only part one of bty
break;
}
case 4:
{
plot4(one4, two4, date4[0], time4[0], bty4[0]); // sending only part one of bty
break;
}
case 5:
{
plot5(one5, two5, date5[0], time5[0], bty5[0]); // sending only part one of bty
break;
}
}
mut2.ReleaseMutex();
}
So you mentioned you run separate threads to add the markers and routes. This can result in threading issues. The UI thread tries to draw your markers and therefore iterates over the lists of markers. When another thread adds a marker to the collection of markers that are being currently drawn, then the iterator becomes invalid, hence the exception is thrown.
The solution: Make sure the adding of the markers happens in an UI synchronized manner.
As a simple first approach to validate the assumption above try your code without threading and then read how to synchronize your threads with the main thread. Basically the eventual
AddMarker()
has to happen on the main thread.Edit You'll need to apply synchronisation as demonstrated in this link with the help of
InvokeRequired
andBeginInvoke
. Have a look how they update the text control, an uni element as the gmap instance. For this then to work the actual add of the markers has to happen within that action/delegate. Let's try to take it from there and let us know how far you get, please.