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.
Related
I'm trying to understand async/await and read the source code of AsyncMethodBuilder. I thought there must be some code like xxx.Wait() or xxx.WaitOnce() waiting for a task to be completed.
However, I didn't find such code in class AsyncMethodBuilder.
system\runtime\compilerservices\AsyncMethodBuilder.cs
https://referencesource.microsoft.com/#mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs,96
So I keep digging, tried to read the source code of Task, TaskScheduler, ThreadPoolTaskScheduler, ThreadPool.
Finally I got class _ThreadPoolWaitCallback, but didn't find any caller.
https://referencesource.microsoft.com/#mscorlib/system/threading/threadpool.cs,d7b8a78b4dd14fd0
internal static class _ThreadPoolWaitCallback
{
[System.Security.SecurityCritical]
static internal bool PerformWaitCallback()
{
return ThreadPoolWorkQueue.Dispatch();
}
}
Another possible code is in class SynchronizationContext, method SetWaitNotificationRequired()
https://referencesource.microsoft.com/#mscorlib/system/threading/synchronizationcontext.cs,8b34a86241c7b423
protected void SetWaitNotificationRequired()
{
...
RuntimeHelpers.PrepareDelegate(new WaitDelegate(this.Wait));
...
But I didn't know what RuntimeHelpers.PrepareDelegate is doing, which is a native method.
Please give some advice. Is there a Wait? And if it is, where it is?
In a correctly implemented async implementation: there is no wait. Instead, at the bottom of the chain, some code exists that will create some async source, which could be a TaskCompletionSource<T>, an IValueTaskSource[<T>], or something similar - which allows that code to store that token somewhere (for example, in a queue, a correlation dictionary, or an async state object for IOCP), and return the incomplete task to the caller. The caller then discovers that it is incomplete, and registers a "when you have the answer, do this to reactivate me" callback. That calling code now unwinds completely, with every step saying "when you're done, push here", and the thread goes on to do other things, such as service a different request.
At some point in the future (hopefully), the result will come back - again, via IOCP, or via a separate IO reader pulling a response from somewhere and taking the appropriate item out of the queue/correlation-dictionary, and says "the outcome was {...}" (TrySetResult, TrySetException, etc).
For all of that time no threads were blocked. That is, ultimately, the entire point of async/await: to free up threads, to increase scalability.
In incorrectly implemented async systems: anything and everything is possible, including async-over-sync, sync-over-async, and everything else.
I searched online but there is very little information regarding ThreadHelper.JoinableTaskFactory.RunAsync
If I have the following code, Test1 runs on MainThread:
public bool Test1()
{
// Do something here
ThreadHelper.JoinableTaskFactory.RunAsync(this.Test2);
// Do something else
return false;
}
private async Task Test2()
{
await TaskScheduler.Default;
// do something here
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
// do something here
}
Is it ok if the RunAsync has never been awaited on? What would happen if Test1 returns before Test2 finishes running?
Is it ok if the RunAsync has never been awaited on?
That depends. It's OK from JoinableTaskFactory's perspective. All the necessary continuations will continue -- it's just that your calling method won't wait for it to complete, which is the whole point of not awaiting it if you choose to do so.
But in general, it may not be healthy for your app. Consider the case that your async work is saving a file (or transmitting something over the network) and the user closes your app. Wouldn't you want the app to wait for it to finish before closing? As #GrzegorzSmulko said in his answer, the JoinableTaskFactory prescribes a pattern for blocking on shutdown (or disposal of your object) to ensure async work completes.
There's another reason to track your async work if you're in an app that hosts the CLR and shuts it down before exiting: you don't want managed threads running around doing arbitrary things when the AppDomain is being finalized or you'll find that your app crashes on shutdown. This is not a concern when you have a pure-managed app though, since it just exits without shutting down the CLR. It will not crash, but it will still abandon any half-done work.
All the foregoing is true in any app that you use JoinableTaskFactory for. If you happen to be using it within Visual Studio (I'm speaking generally here for a broader audience... I know your question specifically mentioned VS) then the rules are stressed more. You should track all your async work as prescribed in that section. You shouldn't have any "fire and forget" work.
The FileAndForget extension method is actually intended for internal Microsoft use since it sends errors to our telemetry servers. If you really want to just forget stuff, you can use the .Forget() extension method. But remember you should only use that after scheduling the work using an AsyncPackage.JoinableTaskFactory instance or another one that is tracking your async work for disposal. Don't use it on ThreadHelper.JoinableTaskFactory because that doesn't track async-and-forgotten work. So for example, don't do this:
ThreadHelper.JoinableTaskFactory.RunAsync(async () => { /* something async */ }).Forget();
The problem with the above is that the async work will not be tracked, and thus not block shutdown. You should do this instead:
myAsyncPackage.JoinableTaskFactory.RunAsync(async () => { /* something async */ }).Forget();
Or even better: just await the call, in which case you can use pretty much any JTF instance:
await ThreadHelper.JoinableTaskFactory.RunAsync(async () => { /* something async */ });
But if you're in a context where you can use await, you often don't need JoinableTaskFactory.RunAsync at all, since if you can just await the code within the delegate itself. Some uncommon scenarios may require that you still track the async work with a JoinableTaskCollection where you might want to use await someJtf.RunAsync but normally you can just drop JTF use where you can naturally await your work.
According to Threading Cookbook for Visual Studio you should use ThreadHelper.JoinableTaskFactory.RunAsync() together with FileAndForget().
The potential problem is, that FileAndForget() is not available in VS2015, but only in VS2017+.
Is it ok if the RunAsync has never been awaited on?
I think it's not ok, you should use FileAndForget. But, I don't really know what to do for VS2015.
What would happen if Test1 returns before Test2 finishes running?
This should be pretty easy to test to make sure. I assume that Test2 will just finish later "But you also should be sure your async work finishes before your object claims to be disposed."
I am getting intermittent deadlocks when using HttpClient to send http requests and sometimes they are never returning back to await SendAsync in my code. I was able to figure out the thread handling the request internally in HttpClient/HttpClientHandler for some reason has a SynchronizationContext during the times it is deadlocking. I would like to figure out how the thread getting used ends up with a SynchronizationContext, when normally they don't have one. I would assume that whatever object is causing this SynchronizationContext to be set is also blocking on the Thread, which is causing the deadlock.
Would I be able to see anything relevant in the TPL ETW events?
How can I troubleshoot this?
Edit 2:
The place that I have been noticing these deadlocks is in a wcf ServiceContract(see code below) inside of a windows service. The SynchronizationContext that is causing an issue is actually a WindowsFormsSynchronizationContext, which I assume is caused by some control getting created and not cleaned up properly (or something similar). I realize there almost certainly shouldn't be any windows forms stuff going on inside of a windows service, and I'm not saying I agree with how it's being used. However, I didn't write any of the code using it, and I can't just trivially go change all of the references.
Edit: here is an example of the general idea of the wcf service I was having a problem with. It's a simplified version, not the exact code:
[ServiceContract]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
internal class SampleWcfService
{
private readonly HttpMessageInvoker _invoker;
public SampleWcfService(HttpMessageInvoker invoker)
{
_invoker = invoker;
}
[WebGet(UriTemplate = "*")]
[OperationContract(AsyncPattern = true)]
public async Task<Message> GetAsync()
{
var context = WebOperationContext.Current;
using (var request = CreateNewRequestFromContext(context))
{
var response = await _invoker.SendAsync(request, CancellationToken.None).ConfigureAwait(false);
var stream = response.Content != null ? await response.Content.ReadAsStreamAsync().ConfigureAwait(false) : null;
return StreamMessageHelper.CreateMessage(MessageVersion.None, "GETRESPONSE", stream ?? new MemoryStream());
}
}
}
Adding ConfigureAwait(false) to the 2 places above didn't completely fix my problem because a threadpool thread used to service a wcf request coming into here may already have a SynchronizationContext. In that case the request makes it all the way through this whole GetAsync method and returns. However, it still ends up deadlocked in System.ServiceModel.Dispatcher.TaskMethodInvoker, because in that microsoft code, it doesn't use ConfigureAwait(false) and I want to assume there is a good reason for that (for reference):
var returnValueTask = returnValue as Task;
if (returnValueTask != null)
{
// Only return once the task has completed
await returnValueTask;
}
It feels really wrong, but would converting this to using APM (Begin/End) instead of using Tasks fix this? Or, is the only fix to just correct the code that is not cleaning up its SynchronizationContext properly?
Update: we now know we're dealing with a WindowsFormsSynchronizationContext (see comments), for whatever reason in a WCF application. It's no surprise then to see deadlocks since the point of that SyncContext is to run all continuations on the same thread.
You could try to to set WindowsFormsSynchronizationContext.AutoInstall to false. According to its docs, what it does is:
Gets or sets a value indicating whether the WindowsFormsSynchronizationContext is installed when a control is created
Assuming someone creates a WindowsForms control somewhere in your app, then that might be your issue and would potentially be solved by disabling this setting.
An alternative to get rid of an existing SynchronizationContext would be to just overwrite it with null, and later restoring it (if you're nice). This article describes this approach and provides a convenient SynchronizationContextRemover implementation you could use.
However, this probably won't work if the SyncContext is created by some library methods you use. I'm not aware of a way to prevent a SyncContext from being overwritten, so setting a dummy context won't help either.
Are you sure the SynchronizationContext is actually at fault here?
From this MSDN magazine article:
Default (ThreadPool) SynchronizationContext (mscorlib.dll: System.Threading)
The default SynchronizationContext is a default-constructed SynchronizationContext object. By convention, if a thread’s current SynchronizationContext is null, then it implicitly has a default SynchronizationContext.
The default SynchronizationContext queues its asynchronous delegates to the ThreadPool but executes its synchronous delegates directly on the calling thread. Therefore, its context covers all ThreadPool threads as well as any thread that calls Send. The context “borrows” threads that call Send, bringing them into its context until the delegate completes. In this sense, the default context may include any thread in the process.
The default SynchronizationContext is applied to ThreadPool threads unless the code is hosted by ASP.NET. The default SynchronizationContext is also implicitly applied to explicit child threads (instances of the Thread class) unless the child thread sets its own SynchronizationContext.
If the SynchronizationContext you are seeing is the default one, it should be fine (or rather, you will have a very hard time to avoid it being used).
Can't you provide more details / code about what's involved?
One thing that looks immediately suspicious to me in your code (though it may be completely fine) is that you have a using block that captures a static WebOperationContext.Current in request, which will both be captured by the generated async state machine. Again, might be fine, but there's a lot of potential for deadlocks here if something waits on WebOperationContext
Try below; I have found success in similar cases getting into the async rabbit hole.
var responsebytes = await response.Content.ReadAsByteArrayAsync();
MemoryStream stream = new MemoryStream(filebytes);
Response the stream variable.
Hope it helps.
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.
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