I have a WCF function that is executing long time, so I call the function in UI with backgraundworker... I want to give a feature to cancel the execution, so I abort IComunicationObject, the problem is that Service execution is not stoping, Is there any way to stop Service execution in this case?
You may not need a BackgroundWorker. You can either make the operation IsOneWay, or implement the asynchronous pattern. To prevent threading issues, consider using the SynchronizationContext. Programming WCF Services does a great job at explaining these.
Make a CancelOperation() method which sets some static ManualResetEvent in your service. Check this event in your Operation method frequently. Or it can be CancelOperation(Guid operationId) if your service can process multiple operation calls concurrently.
One important thing to understand if you're using the Async calls is that there's still no way to cancel a request and prevent a response coming back from the service once it's started. It's up to your UI to be intelligent in handling responses to avoid race conditions. Fortunately there's a simple way of doing this.
This example is for searching orders - driven by a UI. Lets assume it may take a few seconds to return results and the user is running two searches back to back.
Therefore if your user runs two searches and the first search returns after the second - you need to make sure you don't display the results of the first search.
private int _searchRequestID = 0; // need one for each WCF method you call
// Call our service...
// The call is made using the overload to the Async method with 'UserToken'.
// When the call completes we check the ID matches to avoid a nasty
// race condition
_searchRequestID = _searchRequestID++;
client.SearchOrdersCompleted += (s, e) =>
{
if (_searchRequestID != (int)e.UserState))
{
return; // avoid nasty race condition
}
// ok to handle response ...
}
client.SearchOrdersAsync(searchMessage, _searchRequestID);
Related
Updated below...
So this is a random question that came about from a discussion over what I consider the over usage of await in projects at work...
Not sure why I never tried it until now, other than the fact that it's weird and random, but the fact it does work just makes me wonder...how?
The .Result usage was only used to get the responseMessage. I know that is blocking and no bueno and it is for demo purposes only...
So this endpoint works fine...nothing is awaited
[HttpGet("kitteh")]
public Task<string> GetCatFact()
{
var client = new HttpClient();
var res = client.GetAsync("https://catfact.ninja/fact").Result;
return res.Content.ReadAsStringAsync();
}
There's obviously something in the default ASP.NET pipleline that ultimately unwraps the task in order to return the result...but where...or how?
Is this "less efficient" than awaiting in the endpoint itself as the magic taking place behind the scenes is ultimately just blocking to get the result of the returned task?
Updated
So, I am still skeptical and don't think the answer is as easy as "yes it is blocking" or "not it is not blocking" unless there's some legit proof or something to indicate one way or the other. I tried digging through the code myself, and I still don't have a solid answer but...I do know more than I did before...
I simplified the endpoints I have been testing this with...
[HttpGet("taskstring")]
public Task<string> TaskString()
{
return Task.FromResult("Where does this block?");
}
[HttpGet("asyncstring")]
public async Task<string> AsyncString()
{
return await Task.FromResult("This definitely doesn't block");
}
I stepped through a bunch of code and ultimately landed on ObjectMethodExecutor and AwaitableObjectResultExecutor which sparked some interest.
What appears to happen for both the endpoint versions above is the same or nearly the same, at least the execution of these two endpoints and the code covered below. There's a boatload that goes on during this and even though the rider debugger is great, it's not possible to see a lot of the values while debugging due to "Evaluation is not allowed: The thread is not at a GC-safe point".
When the endpoint is called but prior to the endpoint beginning execution...
ObjectMethodExecutor.ctor is called
This does a lot of inspection of the endpoint to determine a bunch of things
One of the checks is to is determine if the method is "async" and it ultimately calls AwaitableInfo.IsTypeAwaitable to check for the required methods/properties and interfaces to ensure it is
If it is, which in the case of returning Task of string it is, makes sense given the above info
ObjectMethodExecutor.GetExecutorAsync() is called
AwaitableObjectResultExecutor.Execute is then called
this type inherits ActionMethodExecutor which overrides the Execute method
executor.ExecuteAsync(executor type of ObjectMethodExecutorAwaitable) is then called, and awaited
this returns a result of type object, boxing yeah I know
The endpoint then actually executes and returns to AwaitableObjectResultExecutor.Execute
the result is then passed to ConvertToActionResult along with the return type, the T of Task of T and the mapper implementation
the mapped ActionResult is then returned
So...I'm still not certain 100% either way but there is a lot of effort put into inspecting the endpoint that is being called and determining if it's async or not, which would make it seem logical to think this is an attempt to avoid something...maybe blocking?
So...does it block...maybe? Seeing that there is an await from the indirect caller of the endpoint, I'd lean towards, no...but it seems really difficult to say still.
What I do now know is...
It definitely does await the endpoint call, albeit indirectly
It converts the Task of string return type to an IActionResult
An async and task only version seem to follow the exact some flow shown above
A non async version does not
So, based on all of that...#Phil's answer seems to be pretty spot on with what I found...
"The framework supports asynchronous controller actions. In order to do so, it would need to inspect the return value of your methods. If the method returns a Task, it will ultimately await on the result before responding.
Even if your action itself does all the awaiting, it still has to return a Task so the caller will still wait (the alternative being some ugly blocking code)."
Thanks to all for participating in an extremely random question that doesn't hold much value to truly understand
Your assumption here is basically correct...
There's obviously something in the default ASP.NET pipleline that ultimately unwraps the task in order to return the result
The framework supports asynchronous controller actions. In order to do so, it would need to inspect the return value of your methods. If the method returns a Task, it will ultimately await on the result before responding.
Even if your action itself does all the awaiting, it still has to return a Task so the caller will still wait (the alternative being some ugly blocking code).
As has been pointed out in some other posts, there are some performance improvements to be had by not awaiting a returned Task so I would write your action as
public async Task<string> GetCatFact()
{
var client = new HttpClient();
var res = await client.GetAsync("https://catfact.ninja/fact");
return res.Content.ReadAsStringAsync(); // no await
}
Your controller handles waiting for the remote response but delegates waiting for the content stream to the caller.
There's obviously something in the default ASP.NET pipleline that ultimately unwraps the task in order to return the result...but where...or how?
ASP.NET asynchronously waits for your task to complete, and then it sends the HTTP response based on the result of the task. It's logically similar to await: an asynchronous wait.
Is this "less efficient" than awaiting in the endpoint itself as the magic taking place behind the scenes is ultimately just blocking to get the result of the returned task?
Yes. It is less efficient to block.
ASP.NET doesn't block; it asynchronously waits. Blocking ties up a thread. So when the code calls .Result, it will be using a thread just to wait for that HttpClient call to complete.
The proper solution is to keep async and await:
[HttpGet("kitteh")]
public async Task<string> GetCatFact()
{
var client = new HttpClient();
var res = await client.GetAsync("https://catfact.ninja/fact");
return await res.Content.ReadAsStringAsync();
}
This way, while the GetAsync is in progress, the thread is yielded back to the ASP.NET runtime and is available for handling other requests, instead of being blocked waiting for the GetAsync to complete.
More information: Task<string> is part of the method signature. ASP.NET has special understanding of the Task<T> type and knows to asynchronously wait for it. async is not part of the method signature. ASP.NET knows whether your method returns Task, but it has no idea whether it's async (and doesn't care). So, in some situations, it's OK to elide the keywords (as described on my blog, but only when the method implementation is trivial. If there's any logic in the method, keep the async and await.
last time I am thinking about proper using logger in our applications.
For example, I have a controller which returns a stream of users but in the log, I see the "Fetch Users" log is being logged by another thread than the thread on the processing pipeline but is it a good approach?
#Slf4j
class AwesomeController {
#GetMapping(path = "/users")
public Flux<User> getUsers() {
log.info("Fetch users..");
return Flux.just(...)..subscribeOn(Schedulers.newParallel("my-custom"));
}
}
In this case, two threads are used and from my perspective, not a good option, but I can't find good practices with loggers in reactive applications. I think below approach is better because allocation memory is from processing thread but not from spring webflux thread which potential can be blocking but logger.
#GetMapping(path = "/users")
public Flux<User> getUsers() {
return Flux.defer(() -> {
return Mono.fromCallable(() -> {
log.info("Fetch users..");
.....
})
}).subscribeOn(Schedulers.newParallel("my-custom"))
}
The normal thing to do would be to configure the logger as asynchronous (this usually has to be explicit as per the comments, but all modern logging frameworks support it) and then just include it "normally" (either as a separate line as you have there, or in a side-effect method such as doOnNext() if you want it half way through the reactive chain.)
If you want to be sure that the logger's call isn't blocking, then use BlockHound to make sure (this is never a bad idea anyway.) But in any case, I can't see a use case for your second example there - that makes the code rather difficult to follow with no real advantage.
One final thing to watch out for - remember that if you include the logging statement separately as you have above, rather than as part of the reactive chain, then it'll execute when the method at calltime rather than subscription time. That may not matter in scenarios like this where the two happen near simultaneously, but would be rather confusing if (for example) you're returning a publisher which may be subscribed to multiple times - in that case, you'd only ever see the "Fetch users..." statement once, which isn't obvious when glancing through the code.
I'd like to add a service that executes some initialization operations for the system when it's first created.
I'd imagine it would be a stateless service (with cluster admin rights) that should self-destruct when it's done it's thing. I am under the impression that exiting the RunAsync function allows me to indicate that I'm finished (or in an error state). However, then it still hangs around on the application's context and annoyingly looking like it's "active" when it's not really doing anything at all.
Is it possible for a service to remove itself?
I think maybe we could try using the FabricClient.ServiceManager's DeleteServiceAsync (using parameters based on the service context) inside an OnCloseAsync override but I've not been able to prove that might work and it feels a little funky:
var client = new FabricClient();
await client.ServiceManager.DeleteServiceAsync(new DeleteServiceDescription(Context.ServiceName));
Is there a better way?
Returning from RunAsync will end the code in RunAsync (indicate completion), so SF won't start RunAsync again (It would if it returned an exception, for example). RunAsync completion doesn't cause the service to be deleted. As mentioned, for example, the service might be done with background work but still listening for incoming messages.
The best way to shut down a service is to call DeleteServiceAsync. This can be done by the service itself or another service, or from outside the cluster. Services can self-delete, so for services whose work is done we typically see await DeleteServiceAsync as the last line of RunAsync, after which the method just exits. Something like:
RunAsync(CancellationToken ct)
{
while(!workCompleted && !ct.IsCancellationRequested)
{
if(!DoneWithWork())
{
DoWork()
}
if(DoneWithWork())
{
workCompleted == true;
await DeleteServiceAsync(...)
}
}
}
The goal is to ensure that if your service is actually done doing the work it cleans itself up, but doesn't trigger its own deletion for the other reasons that a CancellationToken can get signaled, such as shutting down due to some upgrade or cluster resource balancing.
As mentioned already, returning from RunAsync will end this method only, but the service will continue to run and hence not be deleted.
DeleteServiceAsync certainly is the way to go - however it's not quite as simple as just calling it because if you're not careful it will deadlock on the current thread (especially in local developer cluster). You would also likely get a few short-lived health warnings about RunAsync taking a long time to terminate and/or target replica size not being met.
In any case - solution is quite simple - just do this:
private async Task DeleteSelf(CancellationToken cancellationToken)
{
using (var client = new FabricClient())
{
await client.ServiceManager.DeleteServiceAsync(new DeleteServiceDescription(this.Context.ServiceName), TimeSpan.FromMinutes(1), cancellationToken);
}
}
Then, in last line of my RunAsync method I call:
await DeleteSelf(cancellationToken).ConfigureAwait(false);
The ConfigureAwait(false) will help with deadlock issue as it will essentially return to a new thread synchronization context - i.e. not try to return to "caller context".
I am trying to write a control panel to
Inform about certain KPIS
Enable the user to init certain requests / jobs by pressing a button that then runs a stored proc on the DB or sets a specific setting etc
So far, so good, except I would like to run some bigger jobs where the length of time that the job is running for is unknown and could run over both the script timeout period AND the time the user is willing to wait for a response.
What I want is a "fire and forget" process so the user hits the button and even if they kill the page or turn off their phone they know the job has been initiated and WILL complete.
I was looking into C# BeginExecuteNonQuery which is an async call to the query so the proc is fired but the control doesn't have to wait for a response from it to carry on. However I don't know what happens when the page/app that fired it is shut.
Also I was thinking of some sort of Ajax command that fires the code in a page behind the scenes so the user doesn't know about it running but then again I believe if the user shuts the page down the script will die and the command will die on the server as well.
The only way for certain I know of is a "queue" table where jobs are inserted into this table then an MS Agent job comes along every minute or two checking for new inserts and then runs the code if there is any. That way it is all on the DB and only a DB crash will destroy it. It won't help with multiple jobs waiting to be run concurrently that both take a long time but it's the only thing I can be sure of that will ensure the code is run at all.
Any ideas?
Any language is okay.
Since web browsers are unconnected, requests from them always take the full amount of time. The governing factor isn't what the browser does, but how long the web site itself will allow an action to continue.
IIS (and in general, web servers) have a timeout period for requests, where if the work being done takes simply too long, the request is terminated. This would involve abruptly stopping whatever is taking so long, such as a database call, running code, and so on.
Simply making your long-running actions asynchronous may seem like a good idea, however I would recommend against that. The reason is that in ASP and ASP.Net, asynchronously-called code still consumes a thread in a way that blocks other legitimate request from getting through (in some cases you can end up consuming two threads!). This could have performance implications in non-obvious ways. It's better to just increase the timeout and allow the synchronously blocking task to complete. There's nothing special you have to do to make such a request complete fully, it will occur even if the sender closes his browser or turns off his phone immediately after (presuming the entire request was received).
If you're still concerned about making certain work finish, no matter what is going on with the web request, then it's probably better to create an out-of-process server/service that does the work and to which such tasks can be handed off. Your web site then invokes a method that, inside the service, starts its own async thread to do the work and then immediately returns. Perhaps it also returns a request ID, so that the web page can check on the status of the requested work later through other methods.
You may use asynchronous method and call the query from this method.
Your simple method can be changed in to a asynch method in the following manner.
Consider that you have a Test method to be called asynchronously -
Class AsynchDemo
{
public string TestMethod(out int threadId)
{
//call your query here
}
//create a asynch handler delegate:
public delegate string AsyncMethodCaller(out int threadId);
}
In your main program /or where you have to call the Test Method:
public static void Main()
{
// The asynchronous method puts the thread id here.
int threadId;
// Create an instance of the test class.
AsyncDemo ad = new AsyncDemo();
// Create the delegate.
AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);
// Initiate the asychronous call.
IAsyncResult result = caller.BeginInvoke(
out threadId, null, null);
// Call EndInvoke to wait for the asynchronous call to complete,
// and to retrieve the results.
string returnValue = caller.EndInvoke(out threadId, result);
Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".",
threadId, returnValue);
}
From my experience a Classic ASP or ASP.NET page will run until complete, even if the client disconnects, unless you have something in place for checking that the client is still connected and do something if they are not, or a timeout is reached.
However, it would probably be better practice to run these sorts of jobs as scheduled tasks.
On submitting your web page could record in a database that the task needs to be run and then when the scheduled task runs it checks for this and starts the job.
Many web hosts and/or web control panels allow you to create scheduled tasks that call a URL on schedule.
Alternately if you have direct access to the web server you could create a scheduled task on the server to call a URL on schedule.
Or, if ASP.NET, you can put some code in global.asax to run on a schedule. Be aware though, if your website is set to stop after a certain period of inactivity then this will not work unlesss there is frequent continuous activity.
I need to run a background logic that takes around 25-30 sec inside a WCF method that can't take more than 1 sec to complete. I've decided to wrap that logic into a WaitCallback and pass it to ThreadPool.QueueUserWorkItem right before I exit the web method. Initially it worked ok but now I'm having second thoughts because I suspect that sometimes QueueUserWorkItem method doesn't return in a timely manner as a result web method doesn't respond within 1 sec on a regular basis. Are there any issues with using QueueUserWorkItem inside WCF methods?
No not as such, but your question touches upon a more general problem, what to do with long-running service calls? You can either:
Change the configs so that client and server tolerate long service calls, i.e. increase timeouts
Or, design your service calls with a start / get current progress / get final result API, all of which return quickly:
int jobID = serviceProxy.StartJob();
float progress = serviceProxy.GetJobProgress(int jobID);
Result finalResult = serviceProxy.GetJobResult(int jobID);
This is more work, but a better design, and you now also have to maintain a list of running jobs (your async proceessing which could use QueueUserWorkItem or whatever), but all the service calls would return quickly.