Wednesday, January 09, 2013 5:50 PM
I'm trying to use the above pattern to wrap the sqldatareader. The last line below is causing a problem
Using cmd = connection.CreateCommand cmd.CommandType = CommandType.Text cmd.CommandText = script.ToSql(New SqlServerWriter) connection.Open() Dim asyncReader = Observable.FromAsyncPattern(Of SqlDataReader)(cmd.BeginExecuteReader, cmd.EndExecuteReader)
since the VB compiler is complaining that EndExecuteReader needs an argument for parameter asyncResult. I have checked several C# examples which don't seem to have such a parameter.
Must be something obviously I'm missing. If someone could point me to a correct VB implementation here, I'd be grateful.
Wednesday, January 09, 2013 9:51 PM
> the VB compiler is complaining that EndExecuteReader needs an argument for parameter asyncResult
Here's the signature of EndExecuteReader according to the documentation:
public SqlDataReader EndExecuteReader(IAsyncResult asyncResult)
Clearly there's an IAsyncResult parameter. (I checked all versions of the .NET Framework to be sure, since you didn't specify a version.)
So the problem must be with overload resolution of FromAsyncPattern.
The only other argument is BeginExecuteReader, so let's have a look at that. Each version of the .NET Framework has 4 overloads. Here are the signatures according to the documentation:
IAsyncResult BeginExecuteReader() IAsyncResult BeginExecuteReader(CommandBehavior) IAsyncResult BeginExecuteReader(AsyncCallback, Object) IAsyncResult BeginExecuteReader(AsyncCallback, Object, CommandBehavior)
The latter two meet the requirements for the APM. Perhaps they're ambiguous for overload resolution of FromAsyncPattern, or the compiler is simply choosing the wrong one. So let's see what overloads of FromAsyncPattern are candidates...
You're specifying a single generic type argument, so here are the signatures (excluding return types) of FromAsyncPattern that have a single generic type argument according to the documentation:
FromAsyncPattern<TResult>(Func<AsyncCallback, Object, IAsyncResult>, Func<IAsyncResult, TResult>) FromAsyncPattern<T1>(Func<T1, AsyncCallback, Object, IAsyncResult>, Action<IAsyncResult>)
Looking at the number and order of the parameters, it seems that only the first signature is a valid match and it can only correspond to the third signature of BeginExecuteReader:
IAsyncResult BeginExecuteReader(AsyncCallback, Object)
Note that the second signature doesn't match the fourth signature of BeginExecuteReader because CommandBehavior is in the wrong place, which would put Object where AsyncCallback is expected, though it has the correct number of generic type arguments.
So it looks like we've got our winner. But to my surprise, it also matches the signature of EndExecuteReader.
IAsyncResult BeginExecuteReader(AsyncCallback, Object) SqlDataReader EndExecuteReader(IAsyncResult asyncResult) FromAsyncPattern<TResult>(Func<AsyncCallback, Object, IAsyncResult>, Func<IAsyncResult, TResult>)
Obviously, I didn't try this in Visual Studio. If you place the mouse cursor over FromAsyncPattern, which overload does IntelliSense show that the compiler is choosing?
Thursday, January 10, 2013 9:15 AM
Once again, thx very much. The overload being used was
FromAsyncPattern(Of TResult)(begin As Func(Of AsyncCallback, Object, IAsyncResult), end As Func(of IAsyncResult, TResult) As IObservable(Of TResult)
So I mod'ed my code to
Dim asyncReader = Observable.FromAsyncPattern(Of SqlDataReader)(Function(ac, o) cmd.BeginExecuteReader(ac, o), Function(ar) cmd.EndExecuteReader(ar))
and it is fine, now.
I guess it is just the way that, in VB parlance, 'lambda' subs and functions can be inferred implicitly in C# but needs a bit more coaxing in VB.
Thx for talking me thru it again.