Asynchronous calls within a WCF Service - c#

We have a situation where we need to execute some long running code in the InitializeService method of a Data Service. Currently the first call to the data service fires off the code, but does not receive a response until the long running code has finished. The client is not required to wait for this action to complete. I have attempted to use a new thread to execute the code, however with the code being run we are replacing some files on the server which seems to kill the thread and causes it to bomb out. If I don't have it in a thread it runs fine, but the InitializeService method takes a long time to complete.
Are there any other ways to run this code asynchronously (was thinking maybe there is a way to call another method in the same fashion that a client would)?
Thanks in advance.

All WCF communication is basically Asynchronous. Each call spins up its own thread on the host and the processing starts. The problem you're running into, like many of us, is that the client times out before the host is finished with the work, and there's no easy way around that beyond setting the timeout to some ridiculous amount of time.
It's better to split your processing up into two or more parts, starting the intialization process and finishing the initialization process in separate steps, like this:
One option you could try a duplexed WCF service with a call back function to the client. In other words, client "A" calls the host and starts the initialization routine, but the host immediately sends back the client a value of IntializationStart=True so that the client isn't left waiting for the timeout. Then, when the host has finished compiling the files, it calls the client (which has its own listener) and sends a messages that the initialization is ready. Then the client calls the host and downloads the processed files.
This will works well PC-to-server, or server-to-server.
Another option could work this way: client "A" contacts host and host starts the Initialization routine, again sending back IntializationStarted=True. The host sets an internal (DB) value of FilesReady=False for client "A" until all the files are finished. At that point, host sets its internal value of FilesReady=True. Meanwhile, the client is on a timer, polling the host every minute until it finally receives that FilesReady=True, then it downloads the waiting files.
If you're talking about an iPhone-to-server or Android-to-server, then this is a better route.
You follow?

Related

WCF request returns wrong response

I have a c# application that the client uses wcf to talk to the server. In the background every X seconds the client calls a Ping method to the server (through WCF). The following error has reproduced a couple of times (for different method calls):
System.ServiceModel.ProtocolException: A reply message was received for operation 'MyMethodToServer' with action 'http://tempuri.org/IMyInterface/PingServerResponse'. However, your client code requires action 'http://tempuri.org/IMyInterface/MyMethodToServerResponse'.
MyMethodToServer is not consistent and it falls on different methods.
How can this happen that a request receives a different response?
I think you have a pretty mess problem with async communication, main suggestion (as your question isn't clear very well), is try to identify every request, catch the calls and waiting for them, do asyncronic communication and getting a several work with threading.
As you present it, is a typical architecture problem.
If you present more code, can I suggest some code fixing in my answer and I'll be glad to update my answer.
If this occurs randomly and not you consistently, you might be running in a load-balanced setup, and deployed an update to only one of the servers?
Wild guess: your client uses same connection to do two requests in parallel. So what happens is:
Thread 1 sends request ARequest
Thread 2 sends request BRequest
Server sends reply BReply
Thread 1 receives reply BReply while expecting AReply
If you have request logs on the server, it'll be easy to confirm - you'll likely see two requests coming with short delay from the client host experiencing the issue
I think MaxConcurrentCall and ConcurrencyMode may be relevant here (although I did not touch WCF for a long while)

Is there a way to return a response from an API call to ASP.NET while keeping the instance running?

I am writing an API using ASP.NET and I have some potentially long running code from the different end points. The system uses CQRS and Event Sourcing. A Command comes into to an end point and is then published as an event using MediatR. However the Handlers are potentially long running. Since some of the Requests coming in might be sent to multiple Handlers. This process could take longer than the 12s that AWS allows before returning an Error code.
Is there a way to return a response back to the caller to say that the event has been created while still contining with the process? That is to say fire off a separate task that performs the long running piece of code, that also catches and logs errors. Then return a value back to the user saying the Event has been successfully created?
I believe that ASP.NET spins up a new instance each time a call is made, will the old instance die one a value is returned, killing the task?
I could be wrong with a number of points here, this is my knowledge gleaned from the internet but I could have missunderstood articles.
Thanks.
Yes, you should pass the long-running task off to a background process and return to the user. When the task is complete, notifiy the user with whatever mechanism is appropriate for your site.
But do not start a new thread, what you want is to have a background service running for this, and use that to manage your request.
If a new thread is running the long operation it will remain “open/live” until it finishes. Also you can configure the app pool to always be active.
There are a lot of frameworks to work with long running tasks like Hangfire.
And to keep the user updated with the status of the task you can use SignalR to push notifications to the UI

Call a method after a certain period of time without blocking

I'm making a webserver application, and I have a Listener class which waits for connections and spawns an HTTPConnection, passing it the new Socket created, each time a connect request is made. The HTTPConnection class waits for data asynchronously (using Socket.BeginReceive).
I need the delayed execution for a timeout. If the client fails to send a full HTTP request after a certain amount of time, I want to close the connection. As soon as the HTTPConnection object is constructed, the waiting period should begin, then call a Timeout function if the client fails to send the request. Obviously, I can't have the constructor method paused for a few seconds, so the waiting needs to happen async. I also need to be able to cancel the task.
I could do new Thread(...) and all, but that's very poor design. Are there any other ways to schedule a method to be called later?
You could append all postponed events to some ordered data structure and have a background task checking at certain interval if there's a timeout event that have to be executed.
You could save these events in database also (if you have a lot of clients I imagine it could lead to high memory usage).
Also you background task could get all the expired events from the database and handle them at once.

How to asynchronously wait for response from an external application that intercepts printer output

I have designed a system that is made up of 3 separate applications:
Web Application
WCF Service application that receives requests from the web app, does the appropriate action and prints the result using the SendKeys class SendKeys.SendWait("^p"); (this send a Ctrl + P command that prints whats on the screen).
Console application that intercepts printer output (virtual printer via redmon) via the Console.In (as suggested here
The WCF Service app and Web application can communicate easily, but there is no direct communication between the service app and console application. The console app only starts when there is a printer job and the WCF app doesn't know the result of the print job.
Is there a way to make the WCF Service app recieve feedback from the printed job (whether it was ok or not), so it can send appropriate response back to the web application, without doing Thread.Sleep() each second until the printer app finishes printing and saves the result in a file or database?
Is there a way i could pause the thread in the WCF service app, and resume it (whilst sending information back) from the printer console application when the printing process is done?
Edit:
I managed to find a solution from Richard Blewett's suggestions. The solution would make the WCF service app wait untill the print job is finnished, but it will cause the WCF app to be limited to only making one print job at a time.
I create an EventWaitHandle with some key in the WCF app like this:
EventWaitHandle ewh = new EventWaitHandle(false, EventResetMode.ManualReset, "unique-key");
WaitHandle.WaitAny(new WaitHandle[] { ewh });
And i can return to the thread from the Console app like this:
EventWaitHandle ewh = EventWaitHandle.OpenExisting("unique-key");
ewh.Set();
With Richard's solution this will not be the case, and multiple WCF service calls can be done simultaneously.
Assuming there is a unique identifier for the print job then the console app could call the WCF service to say the print job is either completed OK or failed.
The WCF service would either have to block until the completion call came in (waiting on say a ManualResetEventSlim) or you would have to write the service as an async service so the request thread could be returned to the pool while the print job was in progress.
The reason you need a unique identifier for the print job is you will have to hold a data structure in memory in the service mapping unique id to event so you can signal the correct waiting request when its job is complete
When the WCF service creates a print job it puts an entry in, say, a ConcurrentDictionary mapping printJobId to a non signalled ManualResetEventSlim (one for each print job). It then waits for the event to signal.
Now when the print job completes, the console app in turn calls the WCF service passing its printJobId. This operation does to the dictionary, grabs the event and signals it. The original call now wakes up knowing that the print job is complete.
The status of the print job could also be passed via this dictionary data structure so you would have something like
class PrintJob
{
public PrintJob()
{
Event = new ManualResetEventSlim();
}
public ManualResetEventSlim Event {get; private set;}
public int Status{ get; set;}
}
and the dictionary would map the printJobId to one of these for each print job. The console app called operation would set the status to the outcome of the print job

ObjectDisposedException when using Multiple Asynchronous Clients to Multiple Servers

I've been looking into the Asynchronous Client and Asynchronous Server Socket examples on MSDN and have happily punched up the example that works flawlessly when one Client connects to one Server. My problem is that I need to synchronise a chunk of work with a number of machines so they execute at about the same time (like millisecond difference). The action is reasonably simple, talk to the child servers (all running on the same machine but on different ports for initial testing), simulate its processing and send a 'Ready' signal back to the caller. Once all the Servers have returned this flag (or a time-out occurs), a second message to is passed from the client to the acknowledged servers telling them to execute.
My approach so far has been to create two client instances, stored within a list, and start the routine by looping through the list. This works well but not particularly fast as each client's routine is ran synchronously. To speed up the process, I created a new thread and executed the routine on that for each client. Now this does work allowing two or more servers to return back and synchronise appropriately. Unfortunately, this is very error prone and the code errors with the 'ObjectDisposedException' exception on the following line of the 'ReceiveCallback' method...
// Read data from the remote device.
int bytesRead = client.EndReceive(ar);
With some investigation and debugging I tracked the sockets being passed to the routine (using its handle) and found while it isn't connected, it is always the second socket to return that fails and not the first that does successfully read its response. In addition, these socket instances (based upon the handle value) appear to be separate instances, but somehow the second (and subsequent responses) continue to error out on this line.
What is causing these sockets to inappropriately dispose of themselves before being legitmately processed? As they are running in separate threads and there are no shared routines, is the first socket being inappropriately used on the other instances? Tbh, I feel a bit lost at sea and while I could band-aid up these errors, the reliability of the code and potentially losing returning acknowledgements is not a favourable goal. Any pointers?
Kind regards
Turns out the shared / static ManualResetEvent was being set across the different instances so thread 1 would set the ManualResetEvent disposing the socket on the second thread. By ensuring that no methods / properties were shared / static - each thread and socket would execute under its own scope.

Categories

Resources