I created a lib in C# with standard "Add Service Reference" dialog but methods which are implemented in it return void so i can't bind to them in async workflows. I can't use the interface with Begin* End* because every method has different number of parameters so it says "Wrong parameters count" (something like that). So how can I consume WCF services asynchronously(async because it's intended to be used in s开发者_JAVA百科ilverlight where everything is async)?
I am unclear what the stumbling block is, but the process should be
- have svcutil generate async interfaces (with Begin/End methods)
- use those methods with
FromBeginEnd
to convert to async: http://msdn.microsoft.com/en-us/library/ee340508.aspx - note that if the method returns
void
(unit
) then you'll be usingdo!
rather thanlet!
inside an async workflow
To answer one part of your question: "How do I use FromBeginEnd if the Begin function takes some parameters?"
You can do it through the magic of closures. Here's some examples. As you can see, the extension method takes the parameter, but passes to Async.FromBeginEnd
an anonymous function that matches the signature expected by FromBeginEnd
. The extra parameter is captured in a closure and passed into the real BeginXyz
inside the anonymous function.
You can also use the overload of FromBeginEnd
that takes the additional parameters first, and then the pointers to the Begin/End functions last, as I did in the AsyncGetReadStream
method below - but when there are multiple overloads of BeginXyz
I had trouble getting this to work, so I resorted to using closures for most of them.
open System
open System.Data.Services.Client
type System.Data.Services.Client.DataServiceContext with
member this.AsyncExecute<'a> (uri:Uri) =
Async.FromBeginEnd((fun (cb, state) -> this.BeginExecute<'a>(uri, cb, state)),
(fun iar -> this.EndExecute<'a>(iar) :?> QueryOperationResponse<'a>))
member this.AsyncExecute<'a> (continuation:DataServiceQueryContinuation<'a>) =
Async.FromBeginEnd((fun (cb, state) -> this.BeginExecute<'a>(continuation, cb, state)),
(fun iar -> this.EndExecute<'a>(iar) :?> QueryOperationResponse<'a>))
member this.AsyncExecuteBatch ([<ParamArray>] queries : DataServiceRequest[]) =
Async.FromBeginEnd((fun (cb, state) -> this.BeginExecuteBatch(cb, state, queries)), this.EndExecuteBatch)
member this.AsyncLoadProperty (entity:obj, propertyName:string) =
Async.FromBeginEnd((fun (cb, state) -> this.BeginLoadProperty(entity, propertyName, cb, state)),
this.EndLoadProperty)
member this.AsyncLoadProperty (entity:obj, propertyName:string, continuation:DataServiceQueryContinuation) =
Async.FromBeginEnd((fun (cb, state) -> this.BeginLoadProperty(entity, propertyName, continuation, cb, state)),
this.EndLoadProperty)
member this.AsyncLoadProperty (entity:obj, propertyName:string, nextLinkUri:Uri) =
Async.FromBeginEnd((fun (cb, state) -> this.BeginLoadProperty(entity, propertyName, nextLinkUri, cb, state)),
this.EndLoadProperty)
member this.AsyncSaveChanges () =
Async.FromBeginEnd(this.BeginSaveChanges, this.EndSaveChanges)
member this.AsyncSaveChanges (options:SaveChangesOptions) =
Async.FromBeginEnd((fun (cb, state) -> this.BeginSaveChanges(options, cb, state)),
this.EndSaveChanges)
member this.AsyncGetReadStream (entity:obj, args:DataServiceRequestArgs) =
Async.FromBeginEnd(entity, args, this.BeginGetReadStream, this.EndGetReadStream)
type System.Data.Services.Client.DataServiceQuery with
member this.AsyncExecute () =
Async.FromBeginEnd(this.BeginExecute, this.EndExecute)
精彩评论