VersionNotFoundException

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

Hello,
I have a DataGridView, bound to a typed DataTable (without any TableAdapter
etc.).
The values of that DataTable are changed in a second thread using the
following code:
DataSetOrderManager.DbOrderManagerWlanRow row =
dtWlan.FindByHardwareID(HardwareID);
if (row != null)
row.LastVitalSign = DateTime.Now;
row.LastIP = FromIpAddress.ToString();
row.LastAccessPoint = AccessPointMac;
}

Mostly, this is working fine, but sometimes I get an DataGridView.DataError
with the VersionNotFoundException.

I think, this happans, because the row(s) are changed in a different thread!??
I don't want to "Invoke" to the main thread, because the row(s) will be
changed very often, at worst, maybe 100 times per second!

My first attempt was just catching the DataError Event and ignoring the
error, but then, sometimes I saw wrong values in the datagrid!!
So I added a InvalidateCell in the DataError Event.

Well, it seems to work, but I think, avoiding that error is better!

Now the questions are:
1. Is it OK what I do in the DataError Event, or may this produce problems?
2. The better way: How to avoid the VersionNotFoundException?

Thanks in advance,
Robert Witter
 
Hi Robert,

VersionNotFoundException represents the exception that is thrown when you
try to return a version of a DataRow that has been deleted.
http://msdn2.microsoft.com/en-us/library/system.data.versionnotfoundexceptio
n(VS.80).aspx
[VersionNotFoundException Class ]
1. Is it OK what I do in the DataError Event, or may this produce problems?
In order to answer this question, we should know the reason why datagrider
will get the exception. Would you please provide the exact Error Message
and Stack Trace for us?
2. The better way: How to avoid the VersionNotFoundException?
The same as the above issue, we need detailed information about exception
and perform the further analyze.

Sincerely,
Wen Yuan
Microsoft Online Community Support
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
Hi WenYuan,

the error is:
Context: "Display"
Message: "There is no Original data to access."
Source: "System.Data"
Stack Trace:
at System.Data.DataRow.GetOriginalRecordNo()
at System.Data.DataRow.GetRecordFromVersion(DataRowVersion version)
at System.Data.DataRowView.GetColumnValue(DataColumn column)
at System.Data.DataColumnPropertyDescriptor.GetValue(Object component)
at
System.Windows.Forms.DataGridView.DataGridViewDataConnection.GetValue(Int32
boundColumnIndex, Int32 columnIndex, Int32 rowIndex)

I tested a lot with this issue.
Well, after I increased the speed for the changes by factor 100 (that means
about 1000 changes per second) the error occured very often. Also the
following error occured:

Object reference not set to an instance of an object.
at System.Data.DataView.IsOriginalVersion(Int32 index)
at System.Data.DataRowView.GetColumnValue(DataColumn column)
at System.Data.DataColumnPropertyDescriptor.GetValue(Object component)
at
System.Windows.Forms.DataGridView.DataGridViewDataConnection.GetValue(Int32
boundColumnIndex, Int32 columnIndex, Int32 rowIndex)
at System.Windows.Forms.DataGridViewCell.GetValue(Int32 rowIndex)
at System.Windows.Forms.DataGridViewCell.PaintWork(Graphics graphics,
Rectangle clipBounds, Rectangle cellBounds, Int32 rowIndex,
DataGridViewElementStates cellState, DataGridViewCellStyle cellStyle,
DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts
paintParts)
at System.Windows.Forms.DataGridViewRow.PaintCells(Graphics graphics,
Rectangle clipBounds, Rectangle rowBounds, Int32 rowIndex,
DataGridViewElementStates rowState, Boolean isFirstDisplayedRow, Boolean
isLastVisibleRow, DataGridViewPaintParts paintParts)
at System.Windows.Forms.DataGridViewRow.Paint(Graphics graphics,
Rectangle clipBounds, Rectangle rowBounds, Int32 rowIndex,
DataGridViewElementStates rowState, Boolean isFirstDisplayedRow, Boolean
isLastVisibleRow)
at System.Windows.Forms.DataGridView.PaintRows(Graphics g, Rectangle
boundingRect, Rectangle clipRect, Boolean singleHorizontalBorderAdded)
at System.Windows.Forms.DataGridView.PaintGrid(Graphics g, Rectangle
gridBounds, Rectangle clipRect, Boolean singleVerticalBorderAdded, Boolean
singleHorizontalBorderAdded)
at System.Windows.Forms.DataGridView.OnPaint(PaintEventArgs e)
at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e,
Int16 layer, Boolean disposeEventArgs)
at System.Windows.Forms.Control.WmPaint(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.DataGridView.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd,
Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at
System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32
dwComponentID, Int32 reason, Int32 pvLoopData)
at
System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32
reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32
reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at MEKM3.Program.Main() in
D:\RWSD\Projekte\MEKM3\MekmMain\Program.cs:line 17

I think, changing the row values in a different thread was not a good idea.
I tried it with the same speed and BeginInvoke to change the row values in
the main thread and then it works fine!

I think, I will live with the slightly reduced performance by the 'Invoke',
except you have an idea how to make it thread save.

Sincerely,
Robert Witter
 
Hi Robert,
Thanks for your detailed information.

I think the reason of both issues is the related rows have been removed
from table by another thread.
Message: "There is no Original data to access."
Source: "System.Data"
Stack Trace: at System.Data.DataRow.GetOriginalRecordNo()

The first exception thrown by runtime is because GetOriginalRecordNo()
cannot find the original version data of data. This issue is similar to the
second exception.
"Object reference not set to an instance of an object."
at System.Data.DataView.IsOriginalVersion(Int32 index)
I assume the row must have been modified by another thread in application.
One thread want to read the row from the table, however, this row has been
modified/removed by other thread already. Actually, DataTable is safe for
multithreaded read operations, but not write operations. Invoking is a good
solution. I also suggest you invoke to change the row values by the main
thread. I think this is correct way in such scenario and can save you much
time on the potential issues which may be caused by multithread.

http://msdn2.microsoft.com/en-us/library/system.data.datatable.aspx
[DataTable Class]
Thread Safety
This type is safe for multithreaded read operations. You must synchronize
any write operations.

Hope this helps,
Sincerely,
Wen Yuan
Microsoft Online Community Support
 
Hi WenYuan,

thanks for your Help,
With using Invoke, it's working now.

Best Regards,
Robert Witter
 
Back
Top