I'm learning SignalR using the .Net client (not javascript), and was hoping for some clarification on how to invoke hub proxy methods in a synchronous or asynchronous manner.
Method with no return value
So far I've been doing something like this:-
myHubProxy.Invoke("DoSomething");
I've found this to be asynchronous, which is fine as it's effectively "fire-and-forget" and doesn't need to wait for a return value. A couple of questions though:-
Are there any implications with wrapping the Invoke in a try..catch block, particularly with it being asynchronous? I might want to know if the call failed.
Are there any scenarios where you would want to call a method that doesn't return a value synchronously? I've seen the .Wait() method mentioned, but I can't think why you would want to do this.
Method with return value
So far I've been using the Result property, e.g.:-
var returnValue = myHubProxy.Invoke<string>("DoSomething").Result;
Console.WriteLine(returnValue);
I'm assuming this works synchronously - after all, it couldn't proceed to the next line until a result had been returned. But how do I invoke such a method asynchronously? Is it possible to specify a callback method, or should I really be using async/await these days (something I confess to still not learning about)?
If you want to write asynchronous code, then you should use async/await. I have an intro on my blog with a number of followup resources at the end.
When you start an asynchronous operation (e.g., Invoke), then you get a task back. The Task type is used for asynchronous operations without a return value, and Task<T> is used for asynchronous operations with a return value. These task types can indicate to your code when the operation completes and whether it completed successfully or with error.
Although you can use Task.Wait and Task<T>.Result, I don't recommend them. For one, they wrap any exceptions in an AggregateException, which make your error handling code more cumbersome. It's far easier to use await, which does not do this wrapping. Similarly, you can register a callback using ContinueWith, but I don't recommend it; you need to understand a lot about task schedulers and whatnot to use it correctly. It's far easier to use await, which does the (most likely) correct thing by default.
The .Result property returns a async Task, so the server requests is still performed async.
There is not reason to hold up a thread for the duration of the call thats why you use async.
If you fire the call on the GUI thread its even more important todo it async because otherwise the GUI will not respond while the call is done
1) Yuo need to use the await keyword if you want try catch blocks to actually catch server faults. Like
try
{
var foo = await proxy.Invoke<string>("Bar");
}
catch (Exception ex)
{
//act on error
}
2) I think you ment to ask if its any reason to call it async? And yes like I said, you do not want to block any threads while the request is being made
Related
...without async await...
I would like to demonstrate the classic completion handler logic with Task library. (not with the pure Thread object) So I would like to create a Task instance, run it (against the default thread pool, or any way), and have a completion handler, which runs (probably on the Task's thread) on completion and access to the result.
(I do know now we can use async await, also know about marshaling, also know about ASP.NET threads and contexts, please do not explain those.)
I would like to demonstrate the classic completion handler logic with Task library.
I really don't think this is very useful. It sounds like you're describing continuation passing style, which was not widely adopted among .NET libraries. There was one HTTP library using it, but other than that I did not see much adoption of that pattern in .NET at all. On the other hand, JavaScript (particularly server-side JS) did use CPS quite a bit.
That said, if you really want to do it, you can:
public static void Run<T>(Func<T> action, Action<Exception> onError, Action<T> onComplete)
{
Task.Run(action).ContinueWith(
t =>
{
T result;
try
{
result = t.Result;
}
catch (Exception ex)
{
onError(ex);
return;
}
onComplete(result);
},
default,
TaskContinuationOptions.ExecuteSynchronously,
TaskScheduler.Default);
}
I'm trying to call an asynchronous method from a synchronous method like below:
1. public List<Words> Get(string code)
{
Task<List<Words>> taskWords = GetWordsAsync(code);
var result = taskWords.Result;
return result;
}
private async Task<List<Words>> GetWordsAsync(string code)
{
var result = await codeService.GetWordsByCodeAsync(code);
return result;
}
But this lead to a deadlock, await is not getting the results from the method - GetWordsByCodeAsync
I've done a bit of research and came to know that if we are calling an async method from synchronous method we should use Task.Run
When I changed the code like below, it worked:
2. public List<Words> Get(string code)
{
Task<List<Words>> taskWords = Task.Run<List<Words>>(async () => await GetWordsAsync(code);
var result = taskWords.Result;
return result;
}
private async Task<List<Words>> GetWordsAsync(string code)
{
var result = await codeService.GetWordsByCodeAsync(code);
return result;
}
But I didn't get the context, why it caused a deadlock for 1st way and 2nd one worked fine.
I'd like to know:
What's the difference between two ways?
Is second one the correct way to call async method from synchronous method?
Will using the second method also causes a deadlock at some point of time if the result is large? or is it fail proof(safe) method to use?
Also, please suggest any best practices to better do it as I have to do 5 async calls from a synchronous method - just like taskWords, I have taskSentences etc.,
Note: I don't want to change everything to async. I want to call async method from synchronous method.
I don't want to change everything to async. I want to call async method from synchronous method.
From a technical standpoint, this doesn't make sense. Asynchronous means it doesn't block the calling thread; synchronous means it does. So you understand that if you block on asynchronous code, then it's no longer truly asynchronous? The only benefit to asynchronous code is that it doesn't block the calling thread, so if you block on the asynchronous code, you're removing all the benefit of asynchrony in the first place.
The only good answer is to go async all the way. There are some rare scenarios where that's not possible, though.
What's the difference between two ways?
The first one executes the asynchronous code directly and then blocks the calling thread, waiting for it to finish. You're running into a deadlock because the asynchronous code is attempting to resume on the calling context (which await does by default), and presumably you're running this code on a UI thread or in an ASP.NET Classic request context, which only allow one thread in the context at a time. There's already a thread in the context (the one blocking, waiting for the task to finish), so the async method cannot resume and actually finish.
The second one executes the asynchronous code on a thread pool thread and then blocks the calling thread, waiting for it to finish. There is no deadlock here because the asynchronous code resumes on its calling context, which is a thread pool context, so it just continues executing on any available thread pool thread.
Is second one the correct way to call async method from synchronous method?
There is no "correct" way to do this. There are a variety of hacks, each of which has different drawbacks, and none of which work in every situation.
Will using the second method also causes a deadlock at some point of time if the result is large? or is it fail proof(safe) method to use?
It will not deadlock. What it does, though, is execute GetWordsAsync on a thread pool thread. As long as GetWordsAsync can be run on a thread pool thread, then it will work.
Also, please suggest any best practices to better do it
I have written an article on the subject. In your case, if GetWordsAsync is safe to call on a thread pool thread, then the "blocking thread pool hack" is acceptable.
Note that this is not the best solution; the best solution is to go async all the way. But the blocking thread pool hack is an acceptable hack if you must call asynchronous code from synchronous code (again, it's "acceptable" only if GetWordsAsync is safe to call on a thread pool thread).
I would recommend using GetAwaiter().GetResult() rather than Result, in order to avoid the AggregateException wrapper on error. Also, the explicit type arguments are unnecessary, and you can elide async/await in this case:
var taskWords = Task.Run(() => GetWordsAsync(code));
return taskWords.GetAwaiter().GetResult();
I have a very bizarre situation regarding a Web Application that makes an asynchronous Http Post...
We have two branches in TFS. I merged code from one branch to another and then find that some Integration Tests in the new branch fail due to a System.NullReferenceException. I spend time ensuring that our code in both branches is identical, and all the referenced DLLs are identical too. Everything seems identical.
So, I decide to debug the test.
What our test does is to create a Mock IHttpClient object. We stub the Mock object in such a way that the clientMock.PostAsyncWithResponseMessage(x,y) returns a new HttpResponseMessage() object (on which we've set various properties).
So, the code looks like this:
using (var response = await client.PostAsyncWithResponseMessage(url, postData).ConfigureAwait(true))
{
if (response.IsSuccessStatusCode)
{
ret.Response = await response.Content.ReadAsStringAsync().ConfigureAwait(true);
ret.ContentType = response.Content.Headers.ContentType.ToString();
}
ret.StatusCode = response.StatusCode.ToInt();
}
Taking this a line at a time:
await client.PostAsyncWithResponseMessage(url, postData).ConfigureAwait(true))
This looks like it's an async method, but "client" is our Mock object so all it is doing is supporting the IHttpClient interface. If you inspect the Thread, the ID does not change when executing this line.
Later on, we have:
await response.Content.ReadAsStringAsync().ConfigureAwait(true);
Now, when this line executes, the HttpContext.Current is set to null - all our context is trashed. In this application, we do not call ConfigureAwait(false) anywhere, so as far as I'm aware there's no reason why we should lose the context.
If I change that line to:
response.Content.ReadAsStringAsync().Result;
Then this is of course blocking and we don't lose the context.
So two questions:
Why would the await method().ConfigureAwait(true) lose the context? [More marks will of course be awarded if one can also suggest why identical code from one TFS branch fails whilst working in a different branch, but I'm not expecting that]
I can see the obvious benefits of awaiting the .PostAsyncWithResponseMessage(url, postData) method since our thread would otherwise be blocked as the other server processed our request. However, having retrieved the data, what advantage is there in awaiting the ReadAsStringAsync()....in other words, is there a good reason not to use the .Result syntax?
thanks
If you inspect the Thread, the ID does not change when executing this line.
This does not necessarily mean that it ran synchronously. Most unit test frameworks provide a free-threaded context (SynchronizationContext.Current is null) and run their tests on a thread pool thread. It is entirely possible for the code to just happen to resume on the same thread (especially if you were only running one test).
Now, when this line executes, the HttpContext.Current is set to null - all our context is trashed. In this application, we do not call ConfigureAwait(false) anywhere, so as far as I'm aware there's no reason why we should lose the context.
I assume SynchronizationContext.Current is set to null, so there isn't actually a context. What's probably happening is that the test is setting HttpContext.Current (on some random thread pool thread), and after the first truly asynchronous operation, sometimes the test resumes on a thread where Current is set and sometimes it doesn't.
On ASP.NET, there's a request context (SynchronizationContext) that handles the propagation of HttpContext.Current. If you don't have something similar in your unit tests, then there's no context to preserve HttpContext.Current.
If you are looking for a quick fix, then you can probably use my AsyncContext type. This will provide a single-threaded context so that all your asynchronous code will resume on the same thread - not the same semantics as ASP.NET's context, but similar enough to be useful for some tests:
void TestMethod()
{
AsyncContext.Run(async () =>
{
// Test method body goes here.
});
}
On a side note, ConfigureAwait(true) is just noise; true is the default behavior.
is there a good reason not to use the .Result syntax?
It's not clear from your code that the server's response is actually read by the time PostAsyncWithResponseMessage completes. Based on the descriptions of your problem (and the fact that Result fixes it in your tests), it sounds like ReadAsStringAsync is in fact acting asynchronously.
If this is the case, then there are two good reasons not to block: 1) You're blocking a thread unnecessarily, and 2) You're opening yourself up to deadlock.
The applications in my project were until now communicating over qtdbus using synchronous calls. However I now need to convert a few of these calls to asynchronous.
For that I chose to use this API available in qtdbus
QDBusAbstractInterface::callWithCallback
But the problem is that the current implementation has these qtdbus sync calls scattered in a lot of places in the code and the code snippets which follow these sync calls assume that the control only reaches them when the preceding call has been successfully serviced and a reply is obtained.
This will no longer be the case when the calls change to async. Moreover the calls are made in different contexts, so I will be required to maintain the state of the system before each qtdbus call, so that I know what to do when I receive the reply.
Is there any chance really to somehow convert the calls to async without rupturing the fabric of the current code in a big way?
One approach I can think of is to use the FSM pattern.
Any hints or design suggestions will be much appreciated.
Thanks!
The way I am understanding is that you will need to call the same method and then process the return value differently based on the state at the time of the call. Such as
void function()
{
//do stuff
value = SynchronousCall();
if (state == 1)
{
doSomething(value);
}
else
{
doSomethingElse(value);
}
}
I would recommend instead of a full implementation of the Finite State Machine pattern which can make a mess with the number of classes that it adds, add separate methods for each state
void function()
{
//do stuff
if (state == 1)
{
callback = *doSomething(ValueType);
}
else
{
callback = *doSomethingElse(ValueType);
}
callWithCallback(method,args, receiver,callback,error);
}
Then in each method you can assume the state and process the return value accordingly.
Another slightly (very) hacky way would be to simply have a spin wait after all the asynchronous calls and use a QThread:: yield() in the loop while you wait for the value to return. That way it is still technically an asynchronous call but it acts synchronous.
I have a function that loads a user object from a web service asynchronously.
I wrap this function call in another function and make it synchronous.
For example:
private function getUser():User{
var newUser:User;
var f:UserFactory = new UserFactory();
f.GetCurrent(function(u:User):void{
newUser = u;
});
return newUser;
}
UserFactory.GetCurrent looks like this:
public function GetCurrent(callback:Function):void{ }
But my understanding is there is no guarantee that when this function gets called, newUser will actually be the new user??
How do you accomplish this type of return function in Flex?
This way madness lies.
Seriously, you're better off not trying to force an asynchronous call into some kind of synchronous architecture. Learn how the event handling system works in your favour and add a handler for the result event. In fact, here's the advice straight from the flexcoders FAQ :
Q: How do I make synchronous data calls?
A: You CANNOT do synchronous calls. You MUST use the result event. No,
you can't use a loop, or setInterval or even callLater. This paradigm is
quite aggravating at first. Take a deep breath, surrender to the
inevitable, resistance is futile.
There is a generic way to handle the asynchronous nature of data service
calls called ACT (Asynchronous Call Token). Search for this in
Developing Flex Apps doc for a full description.
See my answer here:
DDD and Asynchronous Repositories
Flex and Flash Remoting is inherently asynchronous so fighting against that paradigm is going to give you a ton of trouble. Our service delegates return AsyncToken from every method and we've never had a problem with it.
If you want to ensure that the application doesn't render a new view or perform some other logic until the result/fault comes back, you could do the following:
Attach an event listener for a custom event that will invoke your "post result/fault code"
Make the async call
Handle the result/fault
Dispatch the custom event to trigger your listener from #1
Bear in mind this going to lead to a lot of annoying boilterplate code every time you make an async call. I would consider very carefully whether you really need a synchronous execution path.
You can't convert async call into sync one without something like "sleep()" function and as far as I know it is missing in AS3. And yes, it is not guaranteed that newUser would contain user name before return statement.
The AS3 port of the PureMVC framework has mechanisms for implementing synchronous operations in a Model-View-Controller context. It doesn't try to synchronize asynchronous calls, but it lets you add a synchronous application pattern for controlling them.
Here's an example implementation: PureMVC AS3 Sequential Demo.
In this example, five subcommands are run sequentially, together composing a whole command. In your example, you would implement getUser() as a command, which would call commandComplete() in the getURL() (or whatever) callback. This means the next command would be certain that the getUser() operation is finished.