Good day!
I have a multi-thread application, which purpose, in general, process a very fast populating message queue. Messages are added to queue by one thread and another thread process them.
In processing thread some messages must be shown in grid. Grid's DataSource is DataTable. Processing thread works with DataTable (on each message processing; NID, SID, BID - is a part of 1 message):
Lockers[5].WaitOne();
Continue = true;
for (int i = 0; i <= mDataSource.Tables["Stations"].Rows.Count - 1; i++)
{
DataRow Current = mDataSource.Tables["Stations"].Rows[i];
if ((ushort)Current["SID"] == SID &&
(ushort)Current["NID"] == NID &&
(ushort)Current["BID"] == BID)
{
Continue = false;
break;
}
}
if (Continue &&)
{
SyncContext.Post(x =>
{
mDataSource.Tables["Stations"].BeginLoadData();
mDataSource.Tables["Stations"].Rows.Add(
(fbn + 1) * 10 + 1 + dn,
DeviceList[fbn].Main.Receivers[dn].Channel,
DeviceList[fbn].Main.Receivers[dn].Pilot, SID, NID, BID,
DeviceList[fbn].Receivers[dn].MCC, Latitude, Longitude);
mDataSource.Tables["Stations"].EndLoadData();
},
null);
}
Lockers[5].ReleaseMutex();
Lockers[5] - Mutex object, mDataSource - DataSet object. SynContext - is a synchronization context of main application form. As i say above message queue is quite fast populating, so this code fires about 500 times in 1 second in runtime. And in message queue may be repeats, so i mustn't shown them. Problem that on a few first iterations of message processing thread I get mDataSource.Tables["Stations"].Rows.Count = 0, so because of that my Continue variable = true and i have a repeats in my table. In next iterations I also see in logs that rows was added in table, but Count may be still 2 (but in logs there 17 rows added). Why it could be?
I tried change Mutex object on lock(){} operator. It is not helped me. I tried change DataTable on BindingList. It is not helped me. I can lower a count of repeats in table by creating global variable private readonly int[] LastAddedStation = new int[3]; and add such expression in if block (if (Continue){}): LastAddedStation[0] != SID || LastAddedStation[1] != NID || LastAddedStation[2] != BID . It is helped me to lower repeats in table, but, in my opinion, it is "smells". Is there any clear ways to help my situation?
What I am doing wrong? What is the best practices on high load work with DataTables?
P.S. I'm sorry for my English, I'm not native speaker.
Mainly, it is answered here - What is the difference between SynchronizationContext.Send and SynchronizationContext.Post? .
Post method works in asynchronous mode - "drop off and continue". So it seems that on next iteration code in post method hasn't been completed yet.
I choose to add a separate counter to count added rows and check it with DataTable.Count .