New ASP.NET Web API HttpClient has been giving me some strange results. Here is my code:
class Program {
static async void Main(string[] args) {
var address = "http://localhost:3895/api/urls";
Console.WriteLine(await getStringAsync(address));
Console.ReadLine();
}
public static async Task<string> getStringAsync(string uri) {
var httpClient = new HttpClient();
return await httpClient.GetStringAsync(uri);
}
}
This never comes back and the console suddenly appears and disappears. When I change the code as below, it works as it is supposed to:
static void Main(string[] args) {
var address = "http://localhost:3895/api/urls";
Console.WriteLine(getString(address));
Console.ReadLine();
}
public static string getString(string uri) {
var httpClient = new HttpClient();
return httpClient.GetStringAsync(uri).Result;
}
Any idea on what would be the issue?
async on Main is disallowed in the VS11/.NET 4.5 compiler, so I'm assuming you're using the Async CTP. If using .NET 4.5 is at all an option, do make the switch.
That aside, the reason it doesn't work is because async, or more generally, tasks, rely on being able to signal some way for the remainder of the code to be executed. It works with .Result because the code runs synchronously, so the problem doesn't apply.
There is no built-in support for console applications, because they don't normally use message loops in the way that for example WinForms does, but you can look at Microsoft Visual Studio Async CTP\Samples\(C# Testing) Unit Testing\AsyncTestUtilities, notably GeneralThreadAffineContext.cs, to get a basic example that works in console applications too.
Related
I'm trying to call a site via its url to build a webscraper, but when i try to grab the items from the awaited url my application stops and brings up this message:
blablah.exe (process 1512) exited with code 0.
To automatically close the console when debugging stops, enable Tools->Options->Debugging->Automatically close the console when debugging stop
I dont think this is a code issue, perhaps something with my visual studio debugger? for the life of me can't see what it is.
This is a .net core command line app
Some code just in-case
static void Main(string[] args)
{
GetHtmlAsync();
}
private static async void GetHtmlAsync()
{
var url = "https://blahblah.com";
var client = new HttpClient();
var html = await client.GetStringAsync(url);
var htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(html);
var newsList = htmlDoc.DocumentNode.Descendants("table")
.Where(node => node.GetAttributeValue("class","")
.Equals("itemList")).ToList();
Console.WriteLine(newsList);
Console.Read();
}
}
when debugging it never even reaches:
var htmlDoc = new HtmlDocument();
any ideas?
There are a couple problems here
1) When you call GetHtmlAsync() you are not awaiting it, meaning your application continues to run the code after it (of which there is none), leading to the app exiting
2) You should avoid async void except for event handlers, instead return async Task
Modified code might look like this
static async Task Main(string[] args)
{
await GetHtmlAsync();
}
private static async Task GetHtmlAsync()
{
//Do stuff
}
Note that in order to use async Task Main you need to be using at least C# 7.1
The reason it's returning 0 (zero), success, is because it exited without error.
Change the method to:
private static async Task GetHtmlAsync()
And call it like this:
GetHtmlAsync().Wait();
The method will run synchronously, but the app does anyway, as written.
I need a little help to find out my problem. I've used ASP.NET core and i'm fairly familiar with that, although .NET core C# seems to be "crashing" and exiting when trying to make my async request.
I have a method that returns the external IP of the system
private async Task<string> getExternalIP()
{
using (System.Net.Http.HttpClient HC = new System.Net.Http.HttpClient())
{
return await HC.GetStringAsync("https://api.ipify.org/");
}
}
This should work, but it exits when it reaches the HC.GetStringAsync. I've also tried putting a breakpoint on it but it doesn't actually run.
I'm trying to call the method by using
string Address = await getExternalIP();
Any help is thankful, hopefully i'm not just overlooking something.
Thanks!
Your proposed solution is not good at all.
It is synchronous
It can cause a deadlock
As an alternative, try this approach:
private async Task<string> GetExternalIP()
{
using (HttpClient client = new HttpClient())
return await client.GetStringAsync("https://api.ipify.org/");
}
Your calling method should be asynchronous too:
public async Task CallingMethod()
{
// ...
string address = await GetExternalIP();
// ...
}
The reason it was not working for you before was caused by the use of async void instead of async Task (guessed this by the comments).
async void is an asynchronous method that cannot be awaited. That means, you just call it and forget about it. You won't catch any exception, you won't get any return value.
async Task is an awaitable asynchronous method that does not return anything. It is the asynchronous counterpart for a void synchronous method. Furthermore, since it is awaitable, you'll also be able to catch any exception that may rise on the asynchronous code.
Here I'm trying to execute a azure documentdb stored procedure in c#.
static string EndpointUri = "https://asdf.documents.azure.com:443/";
static string PrimaryKey = "X";
static DocumentClient client = new DocumentClient(new Uri(EndpointUri), PrimaryKey);
static void Main(string[] args)
{
var x = doit();
Read();
}
public static async Task<string> doit()
{
StoredProcedureResponse<string> sprocResponse = await client.ExecuteStoredProcedureAsync<string>("/dbs/eew/colls/fff/sprocs/ggg/", "kamal#enadoc.com");
return "";
}
I wanted the method call ExecuteStoredProcedureAsync to be executed a synchronous one. Here is how I did it.
From what i understand this should now work as a synchronous method call because i added await to the request. But it does not work that way.
I'm sure this is happening because of my lack of understanding about async await usage of c#.
I couldn't find a way to resolve this on google.
How can i make this synchronous.
Change
var x = doit();
To
var x = doit().Result;
Note; that will work fine in this simple console app, but can cause deadlocks in a real application. If you must make it sync in a real application, you should do something like this;
var x = Task.Run(() => doit()).Result;
Explaining this goes beyond what I'd easily be able to put in an SO answer, sorry. If you have access to Pluralsight, this is a excellent explanation by Jon Skeet: https://www.pluralsight.com/courses/skeet-async.
Otherwise, C# in A Nutshell (the book) or a tutorial online.
I am trying to understand async method in c#
I have created a wcf service that delay 10 seconds. I am calling the wcf service from a console application the value asyncValue is never sets. It just closes the console app.
Why is the asyncValue never set to Ok?
Wcf Service
[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class AsyncService
{
[OperationContract]
public async Task<string> TimeAsync()
{
await Task.Delay(10000);
return "Ok";
}
}
Console application
static void Main(string[] args)
{
Task<string> asyncValue = GetAsyncTimeFromWcf();
}
private static async Task<string> GetAsyncTimeFromWcf()
{
AsyncService.AsyncServiceClient client = new AsyncService.AsyncServiceClient();
Task<string> asyncTime = client.TimeAsync();
return await asyncTime;
}
For the await keyword to make sense you need to do something with the return value. The purpose of the async/await feature is to allow the application to continue with other, non-related, code until you need to use the result of the awaited task.
In your case, you call await but you don't use the return value, so the Main method continues and effectively exists the application. For example, try
static void Main(string[] args)
{
Task<string> asyncValue = GetAsyncTimeFromWcf();
Console.WriteLine("Waiting for server...");
Console.WriteLine(String.Format("Result = {0}", asyncValue.Result);
Console.ReadKey();
}
You should find the console will output Waiting for server... for 10 seconds then once the server returns it will display Ok.
asyncValue is a Task whose Result will contain the final value when it finishes. You have to wait for this result either by calling asyncValue.Result or by calling asyncValue.Wait() and then check asyncValue.Result.
You can't use await asyncValue or await GetAsyncTimeFromWcf() in the Main method of a Console program, because you can't mark it as async.
Just try:
Task<string> asyncValue = GetAsyncTimeFromWcf();
var time=asyncValue.Result;
Console.WriteLine(time);
Your main method ends before the WCF call returns.
To see the result, you can add the line:
Console.WriteLine(asyncValue.Result);
The call to Result, will Wait for the task to complete, and then get the result.
Everything was working today until it stopped... Below is the minimum source code (I'm using VS 2012 Update 1, .Net 4.5). When I run it, app exits upon calling client.PostAsync() and so it never reaches Console.ReadLine(). Same in debugger, no exception, nothing, exit code 0.
I tried rebooting machine, restarting VS2012 - nothing works.
Again, everything was running today, not sure what changed (no software has been installed etc, all other network apps still work).
Any ideas? I think I'm loosing my mind.
class Program
{
static void Main(string[] args)
{
Run();
}
private async static void Run()
{
using (var client = new System.Net.Http.HttpClient())
{
var headers = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("submit.x", "48"),
new KeyValuePair<string, string>("submit.y", "15"),
new KeyValuePair<string, string>("submit", "login")
};
var content = new FormUrlEncodedContent(headers);
HttpResponseMessage response = await client.PostAsync("http://www.google.com/", content);
Console.ReadLine();
}
}
}
Your problem is that a program normally exits when its Main() method finishes. And your Main() finishes as soon as you hit the await in Run(), because that's how async methods work.
What you should do is to make Run() into an async Task method and then wait for the Task in your Main() method:
static void Main()
{
RunAsync().Wait();
}
private static async Task RunAsync()
{
…
}
In C# 7.1+ you should use async Main instead:
static async Task Main()
{
await RunAsync();
}
private static async Task RunAsync()
{
…
}
Few more notes:
You should never use async void methods, unless you have to (which is the case of async event handlers).
Mixing await and Wait() in a GUI application or in ASP.NET is dangerous, because it leads to deadlocks. But it's the right solution if you want to use async in a console application.