I'm doing some more working with AJAX, and JSON calls, and I've noticed the the SqlCommand Object has a two methods, ExecuteNonQuery(), and ExecuteNonQueryAsync(), what exactly are the differences in these methods?
If you call ExecuteNonQuery your code will wait until it completes.
If you call ExecuteNonQueryAsync your code will continue execution and you can track when the actual call to ExecuteNonQueryAsync completes via Task<int> object that it returns.
Related
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
I am using an http service object to make servlet requests inside a method in flex. The method is being invoked simultaneously in parallel by two events. I could see that both requests have reached the servlet, but only one returns to the result event. Also this behaviours is not consistent . is it possible that parallel invocation of the httpservice result in loss of some requests? I am sure that both requests have reached the servlet and data is returned from it. Its just that the result event is not triggered in certain cases.
Thanks in advance.
Including code to describe the issue better.
Please find the method below. The below method "callServlet" is being invoked by two separate events
private var httpObj:HTTPService=new HTTPService();
private function callServlet(text:String):void{
Alert.show(text);
httpObj = new HTTPService();
httpObj.url=<servlet URL>;
httpObj.method="POST";
httpObj.resultFormat="xml";
httpObj.contentType="application/xml";
var requestString:String=text;
httpObj.request=requestString;
httpObj.addEventListener(ResultEvent.RESULT,onResultMethods);
httpObj.addEventListener(FaultEvent.FAULT,onFaultMethod);
httpObj.send();
}
Each time i call the method, i pass a different "text" variable. I can see that the alert displays the two different texts send to it. And as explained earlier, both requests does reach the servlet and a response is sent from servlet.
But the result event "onResultMethod" is invoked just once.It doesnt invoke the "faultonFaultMethod" either.
Yes, I have seen this problem before, if you are making multiple requests from flex, some of them will be lost, that was back in 3.0 times. Browsers has a way of stopping the number of http calls, they can allow maximum of 2 calls at a time(depends on the browser), may be chain your requests one after the other or use a singleton which manages your calls.
Thanks all for help. I think i ve got the issue though i cannot guarantee the answer to be right.
The above method is called twice by two events. The httpOject variable is a private var global to the method callServlet. The listeners created in this method are being removed in the result and fault handler methods(this is not shown in the code above).
So i believe when multiple events call the method simultaneously there is a chance that the global variable httpObj is modified by both the events and hence both events result in servlet call using the same httpservice object. When the first call returns to the resulthandler i am removing the listener for resulthandler due to which the second result does not reach the resulthandler method.
This is my assumption and as of now i dont have any better solution. Do let me know if anyone comes up with a better explanation.
I was told that Respond.Redirect is an expensive process because it raises a ThreadAbortException. So instead, we should be using the CompleteRequest function instead. So I gave it a try but I noticed the codes below it still runs, which I do not want. I want to instantly force the browser to jump to another website.
Public Shared Sub TestCompleteRequest()
If 1 = 1 Then
System.Web.HttpContext.Current.Response.Redirect("Http://Google.com", False)
System.Web.HttpContext.Current.ApplicationInstance.CompleteRequest()
End If
Throw New ApplicationException("Hello, why are you here?")
End Sub
As for the code above, the ApplicationException is still thrown. But why? :(
One method doesn't replace the other directly. The CompleteRequest() method does not end execution when it's called. So if that's really what you want to do then Response.Redirect(string) would be the way to go.
CompleteRequest() simply bypasses the Response.End() method, which is what generates the ThreadAbortException you mentioned, but crucially CompleteRequest() flushes the response buffer. This means the HTTP 302 redirect response is sent to the browser at the line where you call CompleteRequest(), which gives you a chance to do operations that don't affect the response after it's been sent to the user.
The solution for you really depends on what you need to achieve, can you provide an example of what you're using Response.Redirect for and what other code is in the same method?
Calling a method in the ASP.NET framework deals with the request, but the fact is you're still writing and running VB.NET - there's nothing in the language (nor should there be, I'd say) that indicates 'when this method returns, perform an Exit Sub'.
Who's to say you wouldn't want to execute some more of the method after telling ASP.NET to complete the request, anyway?
Is there any way to make multiple requests to the callback function in asp.net when using the ICallbackEventHandler? I need the results for each result, however, when I iterate through and call the function, I get the result only for the last call. Any way to make it return a result for each call?
This is what I am passing in via javascript:
function NoPostback() {
$(".spans").each(function(index, item) {
CallServer($(item).attr("myattr"));
});
}
In this, myattr is a custom attribute that holds a value (1..10). What I want returned is something like ('you said: ' + id) to be returned for each of the calls, so that I can go ahead and place them in the appropriate holders.
However, only one item is returned which is the final call made. For instance if there are 4 items, it returns only ('you said: 4').
Any idea on how to have all of them returned?
Thanks in advance.
Most Javascript AJAX frameworks either abort any subsequent requests if one is in progress, or they ignore previous requests and only handle the latest. The AJAX request itself will pass through the browser's XmlHttpRequest object, but the rest of the javascript code is running within the pages thread. Currently, there is no concurrent programming with javascript (however this is slated to change.)
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.