==Disclaimer, the information in this post is only relevant for the PDC
alpha of v2.0 Whidbey. Features may change considerably before the beta
ships.
This is going to be a tough area. The books/articles are correct, you can
definitely call EndXXX on the callbacks, that is what the callbacks are
there for. What you can't do is use an ado.net object (or any other non
thread safe object) in multiple threads. So, as long as you are not using
the command or connection object while you are waiting for the callback,
everything will work as expected. In pseudocode:
This will work:
con.Open()
command.BeginExecute(callback)
//do work here, do not use command or connection.*
//on a different thread
on_callback_called
command.EndExecute.
(*If you were not using the callback and where using the waitone/all you can
continue to use connection, create new command and execute on them with
mars)
If you where to use the command or connection while waiting for the callback
there is the possibility of running into multi-threaded issues. The worst
part is that you will get no exception and it will probably work perfectly
while you are testing the app. Then you will deploy and get the strangest
stress issues! I am looking for suggestions on what can be done to avoid
this.
This problem is going to be there for all non thread safe objects, not just
ado. The first thing I tried to do was do a BeginExecuteReader, fill a table
and bind this to a winform grid on the callback. Of course no go because the
table is non thread safe and I am touching it in both the main thread and
the callback. I thought the whole feature was broken until somebody showed
me this workaround:
delegate void UICallback( object param );
void ExecCallback( IAsyncResult ar )
{
using( SqlDataReader r=_cmd.EndExecuteReader( ar ) )
{
DataTable t=new DataTable();
t.Load( r );
this.Invoke( new UICallback( ReBindOnUIThread ), new object[] { t } );
}
}
}
void ReBindOnUIThread( object param )
{
if( param is DataTable )
{
dataGrid1.DataSource=param;
_cmd=null;
}
}
ReBindOnUIThread executes in the main thread so we can bind to the dataGrid
and still be thread safe!
With this I think you have all the tools to solve your problem. Use a
different connection in each of your threads and don't use it while waiting
for the callback, use delegates to rebind to the main thread where
necessary.
Hope this helps,
--
Angel Saenz-Badillos [MS] Managed Providers
This posting is provided "AS IS", with no warranties, and confers no
rights.Please do not send email directly to this alias.
This alias is for newsgroup purposes only.
Lecture Snoddddgrass said:
Your comments on connection thread safety kind of bum me out, but at
least now I understand why it has to be that way. Some of the books/articles
out there are suggesting that using the async callbacks [then calling
EndExecuteNonQuery() on the thread pool thread] is an acceptable way to
handle things. Well, you're still in the alpha stage so I guess I should cut
them some slack!
That's a tough scenario I will have to take a longer look at it. There
should be a way to get async to work for you here, but it is probably not
going to be something off the shelf.
I'd like to hear more of your thoughts on this. This issue has been
plaguing me for some time. You seem to know this ADO.NET stuff really well
and I'd be thrilled to hear your suggestions.
Thanks!