Deriving from DataTable and adding rows in a different thread.

M

Michael Hulthin

Hello, not even sure if this is the right forum for this question but here
goes.. :)

I'm writing a NET Data Provider for our DBMS and got everything working
except one thing. Populating a DataGrid..

All other parts of the Data Provider framework are all interface-based and
therefore rather easy to implement/override as needed, but the DataTable
isn't!

So when my TTDataTable (derived from DataTable) gets notified over TCP/IP
that a cell has changed it's value and I update the DataTable using
something like:
Rows[updateRow.RowId][cell.Ordinal] = cell.Value == null ? DBNull.Value :
cell.Value;

Sooner or later the application will throw an exception somwhere in
System.Windows.Forms.dll whith no callstack at all, very ennoying.. ;)


This happens I _think_ is because the DataTable implementation does not do
something like this when firing the event:
<someevent>Handler eventTarget = <someevent>;
if ( eventTarget != null )
{
if ( eventTarget.Target is ISynchronizeInvoke )
{
ISynchronizeInvoke target = eventTarget.Target as
ISynchronizeInvoke;
target.BeginInvoke( eventTarget, new object[]{ this<,more params
if needed> } );
}
else
{
eventTarget( this, e );
}

One solution would be to throw the event myself in the OnRowChanged method,
but unfortunatly the onRowChangedDelegate (and also the rest of the event)
seems to be private, so...

Another solution would be that I have totally missunderstood how to properly
deriving from a DataTable and populating/updating it from another thread and
if so, I really hope someone here can show me how. :)

Or *gasp* could it be a bug/bad coding/feature from MS? o.O

BTW when not adding the TTDataTable to a grid but instead simply sinking the
events and tracing the events using Debug.WriteLine or to a console, it
works, thats why I think it's a "updating a form from the wrong
thread"-bug..

TIA/

Michael Hulthin
 
M

Miha Markic [MVP C#]

Hi Michael,

It seems to me that you are having problems with threads.
You see, UI controls shuld be touched only from within the thread they were
created in - in other words - you must not touch them in workerthreads.
This is true for binding also - you must not change the content of data from
within another thread when it acts like a datasource.
So, a solution would be to call Control.Invoke method to update the table
from proper thread (note that you'll have to pass a control instance
referenc to table...
 
M

Michael Hulthin

Hi Miha,
thank You for your answer, but I'm afraid You have missunderstood my
question.
I don't have any problems with using threads, my code works. MSs doesn't,
thats my problem. ;)

The event firing code I included will use the Invoke-thingy if the listener
supports the ISynchronizeInvoke-interface, like a windows form for example.
I would also suspect that a DataGrid also support ISynchronizeInvoke since I
think Control supports ISynchronizeInvoke. But not 100% sure on this.

What I have is a DBMS (our product) and it's capable of sending events
whenever changes are made.
To model this I have chosen to derive from DataTable and calling
TTDataTable. Why? Because DataTable is a very good class for handling
inmemorydata from a relational database such as ours. And because it can be
used as a DataGrid's DataSource. The communication with the DBMS is through
sockets and I'm using asynchronous reads thus in a separate thread.

The DataTable detects whenever I make changes to a cell via the Rows
property and Fires events by itself and it is herte my problem lies. That
code (in DataTable) isn't checking if the eventTarget has implemented the
ISynchronizeInvoke-interface but instead simply calls the delegate. Of
course till will eventually wreck havoc. This is my problem but of course
also only a theory, I cannot be sure unless I get my hands on the sourcecode
to DataTable. :)

So, how do I get around this?
I tried overriding the OnRowChanged method, but I can'g get access to the
eventTarget, because the emembervariable (onRowChangedDelegate) is private,
therefor I cannot fire the event myself.. or can I?

Or is there any other DataSources I can override? That fires events the
DataGrid is listening to that is.

But I would really prefer to overide a DataTable since it's so rich of other
useful features.

Is there a way to impersonate the DataTable so I could send events from my
TTDataTable but that DataGrid believes comes from DataTable and thus would
respond to them maybe?

Or in a nutshell, as a .NET Data Provider, how do I make it possible to
display data from our eventbased Realtime DBMS in a plain vanilla DataGrid?
I know I can also write our own datagrid, but why reinvent the wheel...

Just read your answer one more time.. You seem to be saying that I should
call Control.Invoke myself. Could You please tell my how?
<code>
public class TTDataTable : System.Data.DataTable
{
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top