I need to make async request to web resource and use example from this page (link to full example):
HttpWebRequest myHttpWebRequest= (HttpWebRequest)WebRequest.Create("http://www.contoso.com");
RequestState myRequestState = new RequestState();
myRequestState.request = myHttpWebRequest;
// Start the asynchronous request.
IAsyncResult result=
(IAsyncResult) myHttpWebRequest.BeginGetResponse(new AsyncCallback(RespCallback),myRequestState);
But when I am testing the application the execution freeze(on 2-3 sec) on the last line of this code (i can watch it using debugger).
Why? Is it my mistake or it is a standard behaviour of the function?
You can try, I m sure thats better
private void StartWebRequest(string url)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.BeginGetResponse(new AsyncCallback(FinishWebRequest), request);
}
private void FinishWebRequest(IAsyncResult result)
{
HttpWebResponse response = (result.AsyncState as HttpWebRequest).EndGetResponse(result) as HttpWebResponse;
}
Because of chross thread of textbox'value,But this is wpf application i will retag this, btw you can use webclient like
private void tbWord_TextChanged(object sender, TextChangedEventArgs e)
{
WebClient wc = new WebClient();
wc.DownloadStringCompleted += HttpsCompleted;
wc.DownloadStringAsync(new Uri("http://en.wikipedia.org/w/api.php?action=opensearch&search=" + tbWord.Text));
}
private void HttpsCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error == null)
{
//do what ever
//with using e.Result
}
}
It's the standard behaviour.
From the documentation on HttpWebRequest.BeginGetResponse Method:
The BeginGetResponse method requires some synchronous setup tasks to complete (DNS resolution, proxy detection, and TCP socket connection, for example) before this method becomes asynchronous. [...]
it might take considerable time (up to several minutes depending on network settings) to complete the initial synchronous setup tasks before an exception for an error is thrown or the method succeeds.
To avoid waiting for the setup, you can use
HttpWebRequest.BeginGetRequestStream Method
but be aware that:
Your application cannot mix synchronous and asynchronous methods for a particular request. If you call the BeginGetRequestStream method, you must use the BeginGetResponse method to retrieve the response.
The response occurs on a separate thread. Winforms are not multi-thread safe, so you're going to have to dispatch the call on the same thread as the form.
You can do this using the internal message loop of the window. Fortunately, .NET provides a way to do this. You can use the control's Invoke or BeginInvoke methods to do this. The former blocks the current thread until the UI thread completes the invoked method. The later does so asynchronously. Unless there is cleanup to do, you can use the latter in order to "fire and forget"
For this to work either way, you'll need to create a method that gets invoked by BeginInvoke, and you'll need a delegate to point to that method.
See Control.Invoke and Control.BeginInvoke in the MSDN for more details.
There's a sample at this link: https://msdn.microsoft.com/en-us/library/zyzhdc6b(v=vs.110).aspx
Update: As I'm browsing my profile because I forgot i had an account here - i noticed this and I should add: Anything past 3.5 or when they significantly changed the asynchronous threading model here is out of my wheelhouse. I'm out professionally, and while I still love the craft, I don't follow every advancement. What I can tell you is this should work in all versions of .NET but it may not be the absolute pinnacle of performance 4.0 and beyond or on Mono/Winforms-emulation if that's still around. On the bright side, any hit usually won't be bad outside server apps, and even inside if the threadpool is doing its job. So don't focus optimization efforts here in most cases, and it's more likely to work on "stripped down" platforms you see running things like C# mobile packages although I'd have to look to be sure and most don't run winforms but some spin message loops and this works there too. Basically to bottom line, it's not the "best answer" for the newest platforms in every last case. But it might be more portable in the right case. If that helps one person avoid making a design error, then it was worth the time I took to write this. =)
You can use BackgroundWorker add do the whole thing in DoWork
Related
So I've achieved localhost WCF Named Pipes communication between client EXE and server EXE. I can call class methods on the server over localhost. So, it's like an IPC/RPC. However, if the server's class method takes a long time to execute, then it's best for me to throw that into a thread so that the server class method finishes and runs this thread in the background. Okay, fine, but then when the thread is finished its long task, I want to alert the client without having to use a timer on the client that would check that class method. A timer hitting a class method is a lot more inefficient than a raised event. It's like I need to raise an event on the client from the server. Is there an easy way to do this or to at least simulate it, without a lot of confusing work?
This is an answer formulated from my comment to the OP's question
You could make your WCF methods asynchonous then it's a simple matter of async/await or do away with WCF completely and use built-in async with NamedPipeClientStream (which is still await compatible). Not to mention a speed boost in the latter when doing away with verbose XML SOAP encoding
OP:
#MickyD You were right on the async/await thing now that I have studied that and implemented a test that works. That allows me to almost simulate a callback on a long running task and with minimal lines of code
e.g. to build upon the OP's answer but to use async/await correctly:
Client code
private async void button1_Click(object sender, EventArgs e) // <-- note async
{
label1.Text = await client.GetDataAsync(textBox1.Text); // <-- note await. New method
}
Now you could be tempted to use Task.Run but doing so is bad because:
Task.Run is best suited for compute-bound operations which we aren't.
Task.Run will at the most use an expensive thread-pool thread
We're performing an I/O operation and as such can benefit from I/O Completion Ports and "there is no thread" philosphy of IOCP present in Task I/O bound operations. As such when we make the server call via GetDataAsync, we don't waste a thread waiting for a result.
WCF Server
Here we simulate a lengthy operation by waiting, but instead of using Sleep which isn't Task-aware, we use Task.Delay which is an awaitable operation.
Task<string> async GetDataAsync (string text)
{
await Task.Delay (Timespan.FromSeconds(5));
return text + " processed";
}
So, let's say you have a button click in your UI that does a WCF synchronous method call on the WCF service, and that synchronous method takes a long time to run. Obviously, you don't want to block the UI from updating while that long running task executes. Naturally, you might be thinking about a callback. As in, you make the call to the server, and the class method on the server spawns a thread and runs that task, and when it's done, it returns back to the client a result via a callback.
To set that all up on WCF involves many complex, confusing, poorly documented steps, actually. But there's a much easier way, and it doesn't involve WCF code at all, and doesn't involve you changing anything on the WCF service, nor editing any WCF configurations. The trick is introduced in .NET 4.5 and greater. It's called async and await. Here is an example of a button click that calls a WCF service method that takes a long time to run and then returns the result when it's finished, and yet the GUI doesn't lock up and can handle other events.
1. First, to simulate a slow task, edit your WCF service project's shared class method and add this line in before the return result so that you can simulate a 5 second pause:
Thread.Sleep(5000); // requires using System.Threading;
In my case, I put that in my GetData() method.
2. Now switch to your WCF client project. You may have a button click handler that looks like this, as an example:
private void button1_Click(object sender, EventArgs e)
{
string returnString = client.GetData(textBox1.Text));
label1.Text = returnString;
}
So, switch that with three minor changes:
a. Add using System.Threading.Tasks;.
b. Change private void... to private async void... on your button click handler.
c. Utilize await Task.Run(...) with your slow method call.
Thus, the code would look like so:
private async void button1_Click(object sender, EventArgs e)
{
// Task.Run() requires "using System.Threading.Tasks;"
string returnString = await Task.Run(() => client.GetData(textBox1.Text));
label1.Text = returnString;
}
The end result is that when you click the button in the WCF client project, the GetData() class method is called on the WCF service project in a background thread, and, when finished, it comes back to that await statement and returns the result to the variable assignment. In my case, I clicked the button and nothing happened for 5 seconds -- the label with the result string didn't change. However, the GUI wasn't locked up -- I could drag the window around, type in other fields, click other form buttons, and so on. So, it's almost like a callback event handler, but not exactly. Still, it serves the same functionality and can be used in place of a callback event handler in most cases. And it involves far less code.
I have a winforms app. In development mode, when debugging from Visual Studio .NET 2003 (Yes, I know it's old, but this is a legacy project), I get this error when I try to open a new form. In order to open a new form I get an instance of the form and then I call ShowDialog() method, for example:
frmTest test = new frmTest(here my parameters);
test.ShowDialog();
If I press F11 (step into) when debugging it is not crashing, but If in the line where I instantiate the form I press F10 to go into next line, that is, test.ShowDialog(), then it crashes showing this error.
The complete message error is:
"An unhandled exception of type 'System.ApplicationException' occurred
in System.drawing.dll. Additional Information: An attempt was made to
free a mutual exclusion that does not belong to the process"
I have translated last part: Additional information ... since it was appearing in spanish.
The form that I am instantiating with parameters, its constructor, consists on initialize some variables for example:
public frmTest(string param1, string param2)
{
InitializeComponent();
this.param1 = param1;
this.param2 = param2;
}
private void frmTest_Load(object sender, EventArgs e)
{
// here I call a remote webservice asynchronously.
}
Also my form "frmTest" has four pictureboxes, a label, and a button. Three of the pictureboxes contain a png image (it is assigned on design time through Image property), the last picturebox contains a animated gif, also loaded in design time through Image property. Maybe the error occurs due to these images?
TL;DR: Your web request handler will execute on a different thread. Ensure you don't do anything that isn't thread-safe in that handler. You can use Invoke to dispatch your callback handler's code to the main thread.
Diagnosis
The problem here is almost certainly hiding in the missing details of your asynchronous call.
// here I call a remote webservice asynchronously.
Asynchronously is a little bit too vague to be sure what exactly is happening, but there's a very good chance that the asynchronous mechanism that you are using has executed its callback on a different thread from the main UI thread.
Overview
This is common in the .NET model. Asynchronous I/O in the .NET model makes use of threads in a thread pool to handle I/O via I/O Completion Ports (IOCP). It means that when a call like Socket.BeginReceive or WebRequest.BeginGetResponse (or any .NET asynchronous web request that uses similar technology internally) completes, the callback will execute on a thread in the thread pool, not the main thread. This may be surprising to you, since you didn't actively create another thread; you just participated in making asynchronous calls.
You must be very careful about what you do in the callback from your web request as many user-interface / Windows Forms operations are not permitted on any thread other than the main UI thread. Similarly, it may not be the UI itself that is causing you problems, you may have just accessed some resource or object that is not thread safe. Many seemingly innocuous things can cause a crash or exception if you're not careful with multithreading.
To resolve the issue:
If in doubt, in your callback, as early as you can, dispatch (a.k.a. Invoke) the code in your handler so that it runs on the main thread.
A common pattern for doing this would be something like what follows below.
Suppose you have made a call like this:
IAsyncResult result = (IAsyncResult myHttpWebRequest.BeginGetResponse(
new AsyncCallback(RespoCallback), myRequestState);
The handler might be set up like this:
private static void RespCallback(IAsyncResult asynchronousResult)
{
// THIS IS NOT GOING TO WORK BECAUSE WE ARE ON THE WRONG THREAD. e.g.:
this.label1.Text = "OK"; // BOOM! :(
}
Instead, dispatch any necessary processing back to the main thread.
private static void RespCallback(IAsyncResult asynchronousResult)
{
this.Invoke((MethodInvoker) delegate {
// This block of code will run on the main thread.
// It is safe to do UI things now. e.g.:
this.label1.Text = "OK"; // HOORAY! :)
});
}
I'm not advising this as a general best practice. I'm not saying to just immediately dispatch all your handlers back to the main thread. One size does not fit all. You should really look at the specific details of what you do in your handler and ensure you aren't doing thread-specific things. But I am saying that in the absence of any kind of explanation from you about what your asynchronous handlers are doing, the problem would likely be solved by invoking the handler code on the main thread.
Note: Of course, to fix your problem with this technique, it requires that your main thread is running. If you blocked your main thread with a (bad) technique like the one in this example then you'll have to redesign part of your app. Here's an example of something that would require a bigger rework:
// Start the asynchronous request.
IAsyncResult result=
(IAsyncResult) myHttpWebRequest.BeginGetResponse(new AsyncCallback(RespCallback),myRequestState);
// this line implements the timeout, if there is a timeout, the callback fires and the request becomes aborted
ThreadPool.RegisterWaitForSingleObject (result.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), myHttpWebRequest, DefaultTimeout, true);
// The response came in the allowed time. The work processing will happen in the
// callback function.
allDone.WaitOne(); // *** DANGER: This blocks the main thread, the IO thread
// won't be able to dispatch any work to it via `invoke`
Notice the WaitOne call? That blocks execution of the executing thread. If this code executes on the main thread, then the main thread will be blocked until the WebRequest completes. You'll have to redesign so that either you don't block the main thread (my recommendation) or that you more closely examine your callback handler to see why what it's doing is conflicting with other threads.
Application exceptions are not thrown by the framework itself: what-is-applicationexception-for-in-net; Problem should be in the code you have not the framework. Also be sure to check "InvokeRequired" property before taking the action and if it is, run the method using "Invoke" method. Can check c-sharp-cross-thread-call-problem for that.
May be the async call is trying to access UI thread.
Make sure you are not using control properties like TextBox.Text. If so, you just have to pass its value to the async call, or store it in a class variable before the call.
Also, inside an async call you can't assign values to that properties. Use Invoke() instead.
Try to add an exception breakpoint and VS will stop at the instruction causing the exception. The actual stacktrace may help.
Have You tried to close VS's local variable watch window? Maybe it is evaluating something for You on UI components where the accessing thread should be equal to owner thread of UI component!
Note: I'm using C# in Unity, that means version .NET 3.5, so I cannot use await or async keyword..
What will happen to using statement when I put a method in it which works asynchronously?
using (WebClient wc = new WebClient()) {
wc.DownloadFileAsync(urlUri, outputFile);
}
SomeMethod1();
SomeMethod2();
As you know, after the method DownloadFileAsync() is called, SomeMethod1() will be called which is out of the using block while DownloadFileAsync() is still working. So now I'm really confused what would happen to the using statement and the asynchronous method in this case.
Would Dispose() of wc be called at the right time without any problems?
If not, how do I correct this example?
From the comments:
Then how do I avoid this? Just add await keyword?
No, you can't just do that. (And that's why the previously proposed duplicate question was not in fact a duplicate…your scenario is subtly different.) You will need to delay the dispose until the download has completed, but this is complicated by your need to execute two more program statements (at least…it's impossible to know for sure without a good, minimal, complete code example).
I do think you should switch to the awaitable WebClient.DownloadFileTaskAsync() method, as this will at least simplify the implementation, making it simple to retain the using statement.
You can address the other part of the problem by capturing the returned Task object and not awaiting it until after your other program statements have executed:
using (WebClient wc = new WebClient()) {
Task task = wc.DownloadFileTaskAsync(urlUri, outputFile);
SomeMethod1();
SomeMethod2();
await task;
}
In this way, the download can be started, your other two methods called, and then the code will wait for the completion of the download. Only when it's completed will the using block then be exited, allowing the WebClient object to be disposed.
Of course, in your current implementation you undoubtedly are handling an appropriate DownloadXXXCompleted event. If you want, you can continue using the object that way. But IMHO once you have switched over to using await, it's much better to just put after the await the code that needs to execute on the completion of the operation. This keeps all of the code relevant to the operation in one place and simplifies the implementation.
If for some reason you can't use await, then you will have to use some alternate mechanism for delaying the dispose of the WebClient. Some approaches will allow you to continue to use using, others will require that you call Dispose() in the DownloadXXXCompleted event handler. Without a more complete code example, and a clear explanation for why await is not suitable, it would not be possible to say for sure what the best alternative would be.
EDIT:
Since you've confirmed that you don't have access to await in the current code, here are a couple of other options compatible with older code…
One possibility is to just wait in the same thread after starting the operation:
using (WebClient wc = new WebClient()) {
object waitObject = new object();
lock (waitObject)
{
wc.DownloadFileCompleted += (sender, e) =>
{
lock (waitObject) Monitor.Pulse(waitObject);
};
wc.DownloadFileAsync(urlUri, outputFile);
SomeMethod1();
SomeMethod2();
Monitor.Wait(waitObject);
}
}
(Note: one can use any suitable synchronization above, such as ManualResetEvent, CountdownEvent, or even Semaphore and/or "slim" equivalents. I use Monitor simply due to its simplicity and efficiency, and take as granted readers can adjust to accommodate their preferred means of synchronization. One obvious reason one might prefer something other than Monitor is that the other types of synchronization techniques won't run the risk of having the DownloadFileCompleted event handler itself block waiting on the SomeMethod1() and SomeMethod2() methods to complete. Whether this is important depends of course on how long those method calls would take as compared to the file download.)
The above will, however, block the current thread. In some cases this may be fine, but most often the operation is being initiated in the UI thread, and that thread should not be blocked for the duration of the operation. In that case, you will want to forego using altogether and just call Dispose() from the completion event handler:
WebClient wc = new WebClient();
wc.DownloadFileCompleted += (sender, e) =>
{
wc.Dispose();
};
wc.DownloadFileAsync(urlUri, outputFile);
SomeMethod1();
SomeMethod2();
The System.Net.WebClient provides the event DownloadFileCompleted. You could add a handler for that event and dispose of the client at that time.
What is the simplest way to make an HTTP request? I don't need to read the answer, I just want to send a GET request to an url as simple as possible. I'm using .NET framework 3.5. Waiting for a response is not required either.
At this moment I'm using the following, but I'm wondering if there is a better (shorter/doesn't wait for a response) way.
((HttpWebRequest)WebRequest.Create("http://foo.bar/?q=test")).GetResponse();
Waiting for a response is not required either.
Be very careful with that requirement. People seem to love to "fire and forget" for performance reasons right up until there's something wrong with the system. Then they find that the "forget" part means that the system was explicitly designed not to handle error conditions.
Now, having said that, since you're using 3.0 and don't have the luxury of async or the TPL, you may simply be looking at starting a thread to do the work so that the invoked code returns immediately. (The "don't wait for a response" part.) Combine this with wrapping it in a handy method and you have the "short" part as well.
Maybe something like this:
public static void SendRequest(string url)
{
var thread = new Thread(ThisClass.SendRequest));
thread.Start(url);
// maybe do something to monitor the thread object?
}
private static void SendRequest(object url)
{
var response = ((HttpWebRequest)WebRequest.Create(string.Format("{0}", url))).GetResponse();
// You have a response, might as well examine it for success/failure
}
So consuming code would simply call:
ThisClass.SendRequest("http://foo.bar/?q=test");
The idea here is that consuming code doesn't need to wait for a response, but the thread can wait for the response and handle it accordingly. Even if "handling" it simply means doing nothing for success conditions.
Let's say I call
AsyncCallback callback = new AsyncCallback(QueueMessageAdded);
queue.BeginAddMessage(new CloudQueueMessage(message), callback, null);
where QueueMessageAdded is
private static void QueueMessageAdded(IAsyncResult result)
{
queue.EndAddMessage(result);
}
What does EndAddMessage do?
Including waiting for all callbacks to have been called, it is as slow as calling the synchronous version like this:
Parallel.ForEach(messages, message => queue.AddMessage(message));
First approach makes the request asynchronously and therefore your thread does not have to block while waiting for a response. Second approach, on the other hand, will use N threads, each of which will block until a response is received to its respective request.
Please refer to Asynchronous Programming Model (APM) for more information. All End* methods complete the asynchronous operation, meaning it will block until the operation finishes, return the operation's result if any, and do clean-up.
The first approach allow you to use concurrent requests! A single thread, can, with the first approach send hundreds of concurrent messages, even though the latency of a single POST request to get its reply is high. If you look at production code targeting ASB you can see some patterns in how APM/Async is used.