HttpClient.PostAsJsonAsync crashing without throwing exception - c#

I have an ASP.NET MVC app with WebAPI controllers, and a console app that uses these controllers. The console app runs from a scheduled task and fetches data from remote sources, parses it, and posts it to the MVC app before exiting.
This works well for several of the controllers, but one of the calls is crashing the console app without throwing an exception. The caller code which is used for all the controllers:
public async Task<string> Post<T>(string urlRoot, string url, T data)
{
var result = "";
try
{
var httpClient = GetHttpClient(urlRoot);
var response = await httpClient.PostAsJsonAsync(url, data); // Exits here
if (response.IsSuccessStatusCode)
{
result = await response.Content.ReadAsAsync<string>();
}
}
catch (Exception e)
{
Debug.WriteLine(e.ToString());
}
return result;
}
The program exits when calling await httpClient.PostAsJsonAsync(url, data). Using breakpoints, neither the catch block nor the if statement are reached. The call is being made however, as the web API controller is being called with the correct data.
The programs share the same code for the T being passed across the API call.
From the output window:
The program '[9640] ProgramName.vshost.exe: Managed (v4.0.30319)' has exited with code 0 (0x0).
I was wondering whether the size of the posted data could be a problem, but I've not found any documentation stating size limits.
So my questions are:
What could be causing the console app to prematurely exit?
How can I detect this and prevent the program exiting?

One of possible problems, that you just don't await execution of Post method. Here is simplified version of what i am talking about:
static void Main(string[] args)
{
Action testAction = async () =>
{
Console.WriteLine("In");
await Task.Delay(100);
Console.WriteLine("First delay");
await Task.Delay(100);
Console.WriteLine("Second delay");
};
testAction.Invoke();
Thread.Sleep(150);
}
testAction will be aborted on second await Task, and console exits with 0 code. And output will be:
In
First delay
Press any key to continue . . .
In my case, i would just add Console.ReadKey() call at the end of Main method. In your case something different might be required

Please take a look at this question witch enumerates some Exceptions you need to handle:
.NET Global exception handler in console application
Application.ThreadException += MYThreadHandler;
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
Also consider this aproach for Task Exceptions:
static void Main(string[] args)
{
Task<int> task = new Task<int>(Test);
task.ContinueWith(ExceptionHandler, TaskContinuationOptions.OnlyOnFaulted);
task.Start();
Console.ReadLine();
}
static int Test()
{
throw new Exception();
}
static void ExceptionHandler(Task<int> task)
{
var exception = task.Exception;
Console.WriteLine(exception);
}
You can find more detail in one of the answers of this question:
catch exception that is thrown in different thread

Once you hit await control will be returned to the caller of Post.
Rather than have await in the post method, use ContinueWith from the returned task, something like: Task continuation on UI thread or Wait on the returned task: http://msdn.microsoft.com/en-gb/library/dd537610.aspx

I would suggest testing to see if the JSON.Net serializer is capable of serializing your type.

"exited with code 0" means the program exited gracefully. Thus, it might be the caller of Post<T> or even above callers determine that it was time to end the program. If you are familiar with debugging tools such as WinDbg, you can set native breakpoints at ntdll functions to further diagnose the case, but normally you just need to review your code base.

Related

Polly weird behavior (infinite loop?)

I'm using CircuitBreaker with Polly the first time and I'm facing a problem:
My program executes everything without throwing an Error.
As soon as I get to this codeline, the program Executes it and nothing happens. I cant debug any further. The program is executing this method for ever without a timeout:
var cB = Policy.Handle<Exception>()
.CircuitBreakerAsync(3, TimeSpan.FromMinutes(1),
(ex, t) =>
{
Console.WriteLine("Circuit broken!");
},
() =>
{
Console.WriteLine("Circuit Reset!");
});
HttpClient client = new HttpClient();
var response = await cB.ExecuteAsync((ct) => // <--- Executing this line of code lasts forever
{
var request = new HttpRequestMessage(HttpMethod.Get, new Uri(
endPoint
));
return client.SendAsync(request, ct);
}, System.Threading.CancellationToken.None);
This is a .NET Framework 4.8 Project.
I created a new Project. Also a .NET Framework 4.8 Project and copy-pasted the code in the picture
into the new project.
And: It runs fine!!
So I suggest, there is a configuration? or an adjustment? in the Project I'm working in, which isn't allowing Polly to work correctly.
But what can it be? I get no feedback by e.g. an error...
Does somebody know what can interact with Polly like that?
The observed behaviour was that the application did not make any progress and get stuck at the await ExecuteAsync line. Without knowing what the ExecuteAsync does people can suspect:
either we have an infinite loop
or we have a deadlock
Since the Circuit Breaker implementation (so called Engine) does not perform any kind of things that can cause infinite loop that's why we can exclude that as a possible root cause.
cancellationToken.ThrowIfCancellationRequested();
breakerController.OnActionPreExecute();
try
{
TResult result = action(context, cancellationToken);
if (shouldHandleResultPredicates.AnyMatch(result))
{
breakerController.OnActionFailure(new DelegateResult<TResult>(result), context);
}
else
{
breakerController.OnActionSuccess(context);
}
return result;
}
catch (Exception ex)
{
Exception handledException = shouldHandleExceptionPredicates.FirstMatchOrDefault(ex);
if (handledException == null)
{
throw;
}
breakerController.OnActionFailure(new DelegateResult<TResult>(handledException), context);
if (handledException != ex)
{
ExceptionDispatchInfo.Capture(handledException).Throw();
}
throw;
}
So the deadlock has remained as our primary suspect. Back in the old days the ASP.NET MVC was using SynchronizationContext. As Stephen Clearly describe it in detail it was used to continue the operation on the same thread as the invoker of the async method.
In other words the awaiter and the awaitee are waiting for each other. The caller thread waits for the ExecuteAsync to finish and the ExecuteAsync waits for the caller thread to continue.
With the ConfigureAwait(false) you are basically stating that please do not capture the SynchronizationContext, so the ExecuteAsync can continued on any thread it should not be the caller thread.
In case of ASP.NET Core we don't have to worry about this because the SynchronizationContext.Current is null :)

Orphaned async tasks in Azure Functions

What happens if in an Azure Function an async Task is started but orphaned before it finishes (it is never awaited), e.g.:
[Function("FuncAsync")]
public static async Task<HttpResponseData> FuncAsync(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = "FuncAsync")]
HttpRequestData req,
FunctionContext context)
{
var obj = FactoryClass.GetObject(); // return some object with async LongTaskAsync method
obj.LongTaskAsync(); // async Task LongTaskAsync()
return req.CreateResponse(HttpStatusCode.OK);
}
The intention here was (I guess) to initiate a long running process and instantly return from the function.
I assume it is a bad practice but seems to work in a legacy code. I suspect there's no guarantee for the life of that async task and the azure process can be randomly winded up, when no function entry point is running/triggered.
For a console application if a running async Task is orphaned (and keeps running while the process terminates) it is abandoned/killed (and no exception is thrown).
class Program
{
public static async Task RunFuncAsync()
{
try
{
Console.WriteLine("Task started.");
await Task.Delay(10 * 1000);
Console.WriteLine("Task finished."); // this is never executed
}
catch (Exception e)
{
Console.WriteLine("Exception: " + e.Message); // this is never executed
}
}
static async Task MainAsync(string[] args)
{
var t = RunFuncAsync(); // no awaiting - purposefuly
await Task.Delay(5 * 1000);
Console.WriteLine("Exiting.");
}
static void Main(string[] args)
{
MainAsync(args).GetAwaiter().GetResult();
}
}
Output:
Task started.
Exiting.
C:\TestTasks_Console.exe (process 6528) exited with code 0.
To automatically close the console when debugging stops, enable Tools->Options->Debugging->Automatically close the console when debugging stops.
Press any key to close this window . . .
What happens if in an Azure Function an async Task is started but
orphaned before it finishes ?
The answer for the above question which you have is correct that it will get terminated. Azure Functions have many features that make our work a lot easier. However, stateless Azure Functions are not suitable for long running operations which would require to store a state of progress.
For such cases the Durable Functions are the best option. With this the restrictions on execution times no longer apply.
The task-based programming model and async/await are well suited for mapping workflows of Durable Functions.
If you check the Azure Function best practices, you will also find that we should avoid long running function and our function should be stateless.
Another option is to go for the WebJobs. You can use Azure WebJobs to execute custom jobs as background tasks within an Azure Web App
In conclusion, we can say that stateless Azure Functions not recommended for long running operations as you may get timeout issues or like in your case may get terminated.

Difference in output between these two simple implementations of Async and Await

I'm attempting to mimic the same output for two different implementations asynchronous functionality - the only difference in my mind being return mechanisms. I've boiled down the two examples to the most abstract example I can make them.
For example, the first implementation is very simplistic and behaves as I would expect:
Main()
{
DoStuff();
Console.WriteLine("Hello");
}
async void DoStuff()
{
try
{
string output = await Task.Run(() =>
{
return longRunningMethod();
});
Console.WriteLine(output);
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
string longRunningMethod()
{
Console.WriteLine("Sleeping...");
Thread.Sleep(2000);
Console.WriteLine("... woken up!");
return "World!";
}
/*--------- OUTPUT----------
* Hello
* Sleeping...
*...woken up!
* World!
I then thought to myself that it would be more useful if you could use the result of the async method in a method call rather than return void and embed the behaviour into the void method itself.
Using some reference material and muddling along I have something in my mind that I thought would work but, as below, is returning in the incorrect order.
Main()
{
Console.WriteLine(DoStuff().Result);
Console.WriteLine("Hello");
}
async Task<string> DoStuff()
{
try
{
return await Task.Run(() =>
{
return longRunningMethod();
});
}
catch(Exception ex)
{
return ex.ToString();
}
}
string longRunningMethod()
{
Console.WriteLine("Sleeping...");
Thread.Sleep(2000);
Console.WriteLine("... woken up!");
return "World!";
}
/*--------- OUTPUT----------
* Sleeping...
*...woken up!
* World!
* Hello
In my mind the two snippets should basically be synonymous though this is clearly not the case. An error on my part is causing the code to run synchronously.
Either I'm being dumb or I'm fundamentally misunderstanding something.
PS. If anyone has any advice titling a question like this, feel free to edit/comment as I'm aware it's not particularly informative.
If your Main method were an actual Main in the first example, your output could be different. On my machine I get either
> Hello
or
> Sleeping...
> Hello
or
> Hello
> Sleeping...
Depending on ordering of the instructions and whether the other thread actually manages to run the WriteLine before the program terminates.
That is because you're firing a task that is never awaited by anyone. Creating a method that is expected to complete asynchronously but returns void is a very. Very. Bad. Idea.
What happens, in simple terms, is:
you go into DoStuff from Main;
DoStuff creates a Task that represents the execution of the longRunningMethod on the thread pool (these are the semantics of Task.Run);
DoStuff awaits that Task - since it hasn't completed yet, a bunch of hard complicated stuff is done by the async machinery and the control returns to the caller, which is Main;
back in Main, DoStuff returned - that's it, we advance to the next instruction, print Hello and return from the Main;
what happens now depends on many things, but on a run-of-the-mill PC with Windows 10 the app is terminated and all of its threads mercilessly killed - that includes the thread that was dutifully running the longRunningMethod
The take-away about void returning async methods is - don't write them.
In your second example, you're actually waiting for the Task returned by DoStuff, synchronously, which means that when at point 4. in the above description you actually take the Task and block on it until it gets completed. Therefore the longRunningMethod gets to complete, return, DoStuff gets the control back, completes, returns, and unblocks the Main.
To emulate the semantics you want, here's what you can do:
void Main()
{
Task<string> stuff = DoStuff();
Console.WriteLine("Hello");
Console.WriteLine(stuff.Result);
}
You start a Task, do some work and then synchronously block on the async work. Doing that is also bad.
To get to the sweet, idiomatic C# code, you need to use the async Main feature from C# 7.1, which allows you to declare Main as an async Task method:
async Task Main()
{
Task<string> stuff = DoStuff();
Console.WriteLine("Hello");
Console.WriteLine(await stuff);
}
Voila, blocking removed. The async Main doesn't really change that much, especially in a simple console app, but it's good taste to use async/await all the way. It also serves as a pedagogical example in case you're running DoStuff from something other than Main - then it can make a world of a difference.
You are fundamentally misunderstanding something. To quote MSDN. https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/async-return-types
The Result property is a blocking property. If you try to access it before its task is finished, the thread that's currently active is blocked until the task completes and the value is available. In most cases, you should access the value by using await instead of accessing the property directly.
The previous example retrieved the value of the Result property to block the main thread so that the ShowTodaysInfo method could finish execution before the application ended.
Accessing Result on Task blocks the calling thread until the tasks finishes so it can return it's result.
It is generally discouraged to call Result for any reason.

Calling async function with `function().Wait()` works, but `async function()` crashes

I'm calling a 3rd party library from my C# code, and have found that ctx.CreateSiteAsync(communicationSiteInfo).Wait(); works well, while await ctx.CreateSiteAsync(communicationSiteInfo); causes the application to crash. As .Wait() to the best of my knowledge causes the thread to block, I'm interested inn getting the await approach to work.
Here an extract from my code to put the above calls in context:
public async Task createSite(string base_url, SiteConfig siteConfig) {
using(var ctx = new OfficeDevPnP.Core.AuthenticationManager().GetAppOnlyAuthenticatedContext(base_url, this.applicationId, this.applicationSecret)) {
ctx.Load(ctx.Web, p => p.Title);
ctx.ExecuteQuery();
CommunicationSiteCollectionCreationInformation communicationSiteInfo = new CommunicationSiteCollectionCreationInformation {
Title = siteConfig.title,
Url = siteConfig.url,
SiteDesign = siteConfig.siteDesign,
Description = siteConfig.description,
Owner = siteConfig.ownerEmailAddress
};
try {
// This works: ctx.CreateSiteAsync(communicationSiteInfo).Wait();
await ctx.CreateSiteAsync(communicationSiteInfo);
} catch....
If I'm not mistaking, the function I'm calling it this one: ClientContextExtensions.cs.
I'm pretty new to C#, so perhaps the reason for the application crashing is obvious, but I can't see why the await wouldn't work, as the function I'm calling has async Task in it's definition.
EDIT: The weird thing regarding the exception is that the application simply crashes, and the catch clause is never reached. I don't know, but maybe this has something to do with threading or context or something in that the exception thrown in the async function call are not returned to the current thread. The application crashes on the await ctx.CreateSiteAsync(communicationSiteInfo); call.
EDIT 2: It looks as though I can simplify the issue at hand, but using this as an example instead:
public async Task StartMessageQueuePollAsync()
{
while (true)
{
await Task.Delay(1000).ConfigureAwait(false);
}
This causes the code to crash on await Task.Delay(1000).ConfigureAwait(false);. If is instead use Task.Delay(1000).Wait(), the code works as expected.
I see your answer, but I don't think that's the root cause. It's perfectly fine to use static async Task Main(), as long as your project is using C# 7.0 or higher (when that was introduced). If changing that (and making everything else synchronous, as you'd have to after removing async) made the symptom go away, then that means that somewhere along your call stack, you were missing an await.
For example, this works just fine:
using System;
using System.Threading.Tasks;
public class Program
{
public static async Task Main()
{
Console.WriteLine("Hello.");
await Pause();
Console.WriteLine("All done");
}
public static async Task Pause() {
await Task.Delay(1000);
Console.WriteLine("Done pausing");
}
}
But if you remove the await in Main, then the application would end before "Done pausing" is printed. This is because async methods run synchronously at first, but return at the first await that acts on an incomplete Task. (Pause() returns a Task when it hits await Task.Delay(1000) - before the waiting is completed)
So if you don't await an async method, then your code will just move on to the next line before the work is done. Sometimes you actually want this, but often not.
Since it otherwise runs synchronously, replacing the await with .Wait() would halt the thread and the method would not return, making it suddenly "work".
In your code, that means that either you weren't awaiting createSite() or weren't awaiting whatever called the method that called createSite(), etc.
Microsoft has a series of very well-written articles about asynchronous articles that are worth reading. Start here: Asynchronous programming with async and await
Thanks for the comments on my initial post. I got it working now, and believe it's because of I defined the Main method to be async, like this:
static async Task Main().

Fire and forget async method in ASP.NET MVC

The general answers such as here and here to fire-and-forget questions is not to use async/await, but to use Task.Run or TaskFactory.StartNew passing in the synchronous method instead. However, sometimes the method that I want to fire-and-forget is async and there is no equivalent sync method.
Update Note/Warning: As Stephen Cleary pointed out below, it is dangerous to continue working on a request after you have sent the response. The reason is because the AppDomain may be shut down while that work is still in progress. See the link in his response for more information. Anyways, I just wanted to point that out upfront, so that I don't send anyone down the wrong path.
I think my case is valid because the actual work is done by a different system (different computer on a different server) so I only need to know that the message has left for that system. If there is an exception there is nothing that the server or user can do about it and it does not affect the user, all I need to do is refer to the exception log and clean up manually (or implement some automated mechanism). If the AppDomain is shut down I will have a residual file in a remote system, but I will pick that up as part of my usual maintenance cycle and since its existence is no longer known by my web server (database) and its name is uniquely timestamped, it will not cause any issues while it still lingers.
It would be ideal if I had access to a persistence mechanism as Stephen Cleary pointed out, but unfortunately I don't at this time.
I considered just pretending that the DeleteFoo request has completed fine on the client side (javascript) while keeping the request open, but I need information in the response to continue, so it would hold things up.
So, the original question...
for example:
//External library
public async Task DeleteFooAsync();
In my asp.net mvc code I want to call DeleteFooAsync in a fire-and-forget fashion - I don't want to hold up the response waiting for DeleteFooAsync to complete. If DeleteFooAsync fails (or throws an exception) for some reason, there is nothing that the user or the program can do about it so I just want to log an error.
Now, I know that any exceptions will result in unobserved exceptions, so the simplest case I can think of is:
//In my code
Task deleteTask = DeleteFooAsync()
//In my App_Start
TaskScheduler.UnobservedTaskException += ( sender, e ) =>
{
m_log.Debug( "Unobserved exception! This exception would have been unobserved: {0}", e.Exception );
e.SetObserved();
};
Are there any risks in doing this?
The other option that I can think of is to make my own wrapper such as:
private void async DeleteFooWrapperAsync()
{
try
{
await DeleteFooAsync();
}
catch(Exception exception )
{
m_log.Error("DeleteFooAsync failed: " + exception.ToString());
}
}
and then call that with TaskFactory.StartNew (probably wrapping in an async action). However this seems like a lot of wrapper code each time I want to call an async method in a fire-and-forget fashion.
My question is, what it the correct way to call an async method in a fire-and-forget fashion?
UPDATE:
Well, I found that the following in my controller (not that the controller action needs to be async because there are other async calls that are awaited):
[AcceptVerbs( HttpVerbs.Post )]
public async Task<JsonResult> DeleteItemAsync()
{
Task deleteTask = DeleteFooAsync();
...
}
caused an exception of the form:
Unhandled Exception: System.NullReferenceException: Object reference
not set to an instance of an object. at System.Web.ThreadContext.AssociateWithCurrentThread(BooleansetImpersonationContext)
This is discussed here and seems to be to do with the SynchronizationContext and 'the returned Task was transitioned to a terminal state before all async work completed'.
So, the only method that worked was:
Task foo = Task.Run( () => DeleteFooAsync() );
My understanding of why this works is because StartNew gets a new thread for DeleteFooAsync to work on.
Sadly, Scott's suggestion below does not work for handling exceptions in this case, because foo is not a DeleteFooAsync task anymore, but rather the task from Task.Run, so does not handle the exceptions from DeleteFooAsync. My UnobservedTaskException does eventually get called, so at least that still works.
So, I guess the question still stands, how do you do fire-and-forget an async method in asp.net mvc?
First off, let me point out that "fire and forget" is almost always a mistake in ASP.NET applications. "Fire and forget" is only an acceptable approach if you don't care whether DeleteFooAsync actually completes.
If you're willing to accept that limitation, I have some code on my blog that will register tasks with the ASP.NET runtime, and it accepts both synchronous and asynchronous work.
You can write a one-time wrapper method for logging exceptions as such:
private async Task LogExceptionsAsync(Func<Task> code)
{
try
{
await code();
}
catch(Exception exception)
{
m_log.Error("Call failed: " + exception.ToString());
}
}
And then use the BackgroundTaskManager from my blog as such:
BackgroundTaskManager.Run(() => LogExceptionsAsync(() => DeleteFooAsync()));
Alternatively, you can keep TaskScheduler.UnobservedTaskException and just call it like this:
BackgroundTaskManager.Run(() => DeleteFooAsync());
As of .NET 4.5.2, you can do the following
HostingEnvironment.QueueBackgroundWorkItem(async cancellationToken => await LongMethodAsync());
But it only works within ASP.NET domain
The HostingEnvironment.QueueBackgroundWorkItem method lets you
schedule small background work items. ASP.NET tracks these items and
prevents IIS from abruptly terminating the worker process until all
background work items have completed. This method can't be called
outside an ASP.NET managed app domain.
More here: https://msdn.microsoft.com/en-us/library/ms171868(v=vs.110).aspx#v452
The best way to handle it is use the ContinueWith method and pass in the OnlyOnFaulted option.
private void button1_Click(object sender, EventArgs e)
{
var deleteFooTask = DeleteFooAsync();
deleteFooTask.ContinueWith(ErrorHandeler, TaskContinuationOptions.OnlyOnFaulted);
}
private void ErrorHandeler(Task obj)
{
MessageBox.Show(String.Format("Exception happened in the background of DeleteFooAsync.\n{0}", obj.Exception));
}
public async Task DeleteFooAsync()
{
await Task.Delay(5000);
throw new Exception("Oops");
}
Where I put my message box you would put your logger.

Categories