Block thread until WCF callback is raised? - c#

Is it possible to wait on a callback in WCF? Given this article, I will raise a callback in my WCF service, but I want the client (a seperate application) to only proceed (ie go to the next line of code, e.g. close a form etc, after the callback is raised. So I need to block until the callback is raised.
How could I do this?

Instead of using callbacks, you could call the service synchronously from the client.
If the client does not require any data to be returned, you could return a void, and the client will still wait for the call to complete.

Related

How to call a web service in "fire and forget" way from ASP.Net

I have a web service that I want to call from one of my asp.net classes.
I can call my web service successfully.But now I need to call this service asynchronously. I need to call it and NOT wait for the service to complete execution. I don't need to process a response from the service and don't need to verify if the service executed successfully. All I want is to be able to call the service and be free to do other things.
You need to consume web service asynchronously.
Goto and check
AddServiceReference -> Advance -> generate asynchronous operations.
after this async callback events will be available to you for every method
Suppose you have ABC method in you service when you will consume it by as sync these methods will be available to you in your application
1>ABC (fire and wait for output)
2>ABCAsync(fire and forget)
3>ABC callback event(get fired <if ABCAsync is called> when data available in your application)
One way to implement a fire-and-forget approach is to use the IsOneWay property on the OperationContract attribute, like this:
[OperationContract(IsOneWay=true)]
public void SomeMethod(string someValue);
When set to true, the operation won't return a message. Note that methods marked as one-way cannot have return types or ref or out parameters (which makes sense). It also should not be confused with asynchronous calls, because it's not the same thing (in fact, a one-way call can block on the client if it takes a while to get a connection, for example).
See OperationContractAttribute.IsOneWay Property for more information.
Have you tried this:?
http://msdn.microsoft.com/en-us/library/bb885132(v=vs.110).aspx
this is another way to do it, check it out.

events v.s. async methods using TaskCompletionSource

I am currently implementing an application protocol library relying on TCP/IP for transport (long lasting connection).
I am trying to achieve a nice asynchronous implementation relying on TAP pattern using C#5 async/await constructs, mainly to put into practice the concepts I have only seen in theory up until now.
The client can connect to a remote server and send requests to it.
client receives response from the server as well as requests (full duplex mode).
From the point of view of the client code, the asynchronous call to my library to send a request to the server and receive the associated response is as simple as :
var rsp = await session.SendRequestAsync(req);
From inside my protocol library, I am just buliding the request, converting it to bytes (to be sent on the network stream) and I call WriteAsync on the stream and I then await on a Task created just before sending the request, making use of a TaskCompletionSource object, which is basically waiting for the associated response to be received (and setting the result on the tcs), and then return the response to the client caller.
This part seems fine.
Now the "problem" concerns the part where server is sending requests to the client. There are different type of requests that the server can send to the client.
My protocol library is using an asynchronous loop to listen to the underlying stream (receiving incoming responses or requests from the server).
This loop is reading responses/requests asynchronously on the stream, then in case of a request from the server, it raises an event corresponding to the request type (such as ReceivedRequestTypeA). The client code can subscribe to these events to be notified when a specific request type is received from the server. The event args of these contains all the parameters associated with the request as well as a response object, to be set by the client, which will be asynchronously sent on the stream by library once event handler code is completed.
The code for the asynchronous listen loop is as follow. Please do not mind the while true, not very pretty (cancelation pattern should be used instead), but this is not the point !
private async Task ListenAsync()
{
while(true)
{
Request req = await ReadRequestAsync();
await OnReceivedRequest(req);
}
}
So the loop is calling the asynchronous method ReadRequestAsync which is just reading some bytes asynchronously in the stream until a complete request or response is available.
Then it forwards the request to the asynchronous method OnReceivedRequest which code can be seen below :
private async Task OnReceivedRequest(Request req)
{
var eventArgs = new ReceivedRequestEventArgs { Req = req };
if (req is RequestTypeA)
{ ReceivedRequestTypeA(this, eventArgs); }
[... Other request types ...]
await SendResponseAsync(eventArgs.Resp);
}
This asynchronous method raise the appropriate request type event.
The client code is subscribed to this event, so its appropriate event handler method is called ... the client code does whatever it needs with the request and then construct a response and set it in the EventArgs object -end of event handler method-. The code resumes in OnReceivedRequest in the library, and the response is sent asynchronously (calling WriteAsync on the underlying stream).
I don't think this is a good approach, as it can completely block the asynchronous loop in the library if the event handler code on client side is doing a lengthy blocking operation (bye bye fully asynchronous protocol library, you are now becoming somehow synchronous due to client code). The same would happened if I was using an asynchronous task based delegate for events and awaiting on it.
I was thinking that instead of using events, I could have an asynchronous method GetRequestTypeAAsync() which would be implemented using TaskCompletionSource object in library, and the tcs result being set with the request in OnReceivedRequest. And on client code side, instead of subscribing to ReceivedRequestTypeA event, the code would rather consist of a loop arround GetRequestTypeAAsync(). Still as the client code must somehow provide a response to the library to be sent to server, I don't know how this could work ...
My brain is completely fuzzy right now and can't really think clear. Any suggestion for a nice design will be greatly appreciated.
Thanks !
I'm also working on async/await TCP/IP sockets, and I strongly recommend you take a look at TPL Dataflow. It's pretty easy to make async-friendly endpoints using two BufferBlocks (one for reads and one for writes).
In my system, the TCP/IP socket wrapper exposes a simple ISourceBlock<ArraySegment<byte>> representing the raw reads. This is then linked to a TransformManyBlock which performs message framing, and from there it can be linked to a TransformBlock which parses the bytes into actual message instances.
This approach works best if you have a RequestType base class from which all your other message types inherit. Then you can have a single receiving task that just (asynchronously) receives RequestType message instances from the end of the dataflow pipeline.

How to Cancel a RIA Services LoadOperation

I am using RIA services in a Silverlight project. I am using the LoadOperation class on the client side to load some data from the server.
In the process of loading that data the request might be superseded by a newer request for different data. This is based on multiple LoadOperations being made to the server, then the user clicking a cancel button.
If I take my LoadOperation and call the 'Cancel' method on it, the operation seems to cancel, but the server side code is not stopped, and using fiddler I can see that the operation completes and an HTTP status code of 200 is returned.
When you call 'Cancel' what does that do on the server, I would expect it to call a ThreadAbortException or something like that? Can this be improved?
So I had a look at the decompiled RIA Services source and it seems like the cancel is client side only. No change to the server-side process is made.
Basically when you run operation.Cancel(), it makes sure the operation can be canceled (operation.CanCancel), and then marks it as canceled, and triggers the completion action.
This means that the server-side operation still continues, but nothing is done with the response client side when it completes
Once the operation has completed, you'll need to check the operation.IsCanceled property to see if that operation was canceled. If so, just ignore the result.
From what I understand cancel of serverside execution using the loadoperation is not available.
you could tough run your own cancel impelmentation:
(depending on if you are using DomainService base or LinqToEntitiesDomainService base the impelmentation will variate)
sevice side
in your service method start the load in a new thread
put that thread object in the session
your thread object should be in a way that you can cancel the DbConnection...
perpare a service method (Invoke) to Cancel the currently executing
thread object registered in the session, and remove it from the session
client side
call cancel on the LoadOperation object and invoke the cancel request.
one caveat is that you comment out the OnSessionStart and stop in global.asax in order
to execute ria services in a multithreaded way per user else each request will wait till a previous request is finished (this has to do with ria service threads and not our thread object)
hope this helps
best regards
PS: we also use a similar solution for pessimistic lock with RIA Services and EntityFramework, ...

In SignalR is Hub.Context thread safe?

If there is more than one request occurring from different clients simultaneously then the value of Hub.Context.ConnectionId changes during the execution of the handler.
Say I've got 2 clients connected with client Ids A and B, and I've got a method on my Hub called foo(). I send a request from A to the Server invoking foo(), then whilst the request from A is being processed I send a request from B invoking foo(). At the start of the processing of A's request Hub.Context.ConnectionId == A but at the end of the method call Hub.Context.ConnectionId == B.
Should I be copying the Hub.Context? At what point should I do this?
It doesn't need to be thread safe since Hub instances aren't static so you don't need to copy anything.
They are created per call. So each call from the client will create a new Hub instance and HubContext.
This doesn't directly answer your question, but my usual workflow is to set a value on the caller when they first connect, which may accomplish what you need?
Caller.clientId = Guid.NewGuid();

Cancel async web service calls

I need to be able to cancel async calls made to my webservice. One solution I have is to use manage my own threads, and use synchronous methods from the SOAP client. This works fine and it needs some more fine grained thread management.
If I used any of these two patterns provided from adding a web service reference, say:
var Client = new ASL_WS.SvcSoapClient()
IAsyncResult result = Client.BeginAuthenticateUser(Email, Password, new AsyncCallback(AuthCompleted));
or
var Client = new ASL_WS.SvcSoapClient()
Client.AuthenticateUserCompleted += AuthCompleted;
Client.AuthenticateUserAsync(Email, Passsword);
do any of these two patterns give me a way of cancelling the request? One use case could be: a user logs in, but wants to cancel before the authenticate call completes.
Of course, I could implement this differently by modifying the asyncState passed to these calls, and setting it to disable UI update, but it's not what I'm looking for.
Could I just just cancel all outstanding operations. Does Client.Abort() cancel such operations. What if there are many async requests, are all cancelled? Are there any other API methods that can do this?
Yes, you can use Abort method but keep below notes in mind. You can also use CancelAsync.
Abort notes: http://msdn.microsoft.com/en-us/library/aa480512.aspx
When you call the Abort method, any outstanding requests will still complete, but they will complete with a fault. This means that if you are using callbacks, your callback function will still be called for each outstanding request . When the EndInvoke method is called, or in our case, the wrapper function EndDelayedResponse, then a fault will be generated indicating that the underlying connection has been closed.
CancelAsync example: http://www.codeproject.com/KB/cpp/wsasync.aspx

Categories