I want to implement a fire and forget task from within an existing WebAPI service. The code below simply sends a log event (might be that a client has connected to the service to perform some task) to another service and if it fails should not return an error to the client.
I simply want the exception logged and forgotten about, meanwhile the service will continue carrying out the original task.
I've used ContinueWith
:
Task.Factory.StartNew(() =>
{
var client = (HttpWebRequest) WebRequest.Create(_url);
client.Method = "POST";
client.ContentType = "application/json";
var bytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(log));
var requestStream = client.GetRequestStream();
requestStream.Write(bytes, 0, bytes.Length);
requestStream.Close();
var response = client.GetResponse();
requestStream.Close();
response.Close();
}).ContinueWith((ca) =>
{
if (ca.Exception != null)
{
_logger.LogException(LogLevel.Error, ca.Exception.Message, ca.Exception);
}
}, TaskContinuationOptions.OnlyOnFaulted);
Alternatively I'm also thinking that I could do it this way, that is, without using a continuation.
Task.Factory.StartNew(() =>
{
try
{
var client = (HttpWebRequest) WebRequest.Create(_url);
client.Method = "POST";
client.ContentType = "application/json";
var bytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(log));
var requestStream = client.GetRequestStream();
requestStream.Write(bytes, 0, bytes.Length);
requestStream.Close();
var response = client.GetResponse();
requestStream.Close();
response.Close();
}
catch(Exception e)
{
_logger.LogException(LogLevel.Error, e.message, e)
}
})
Are these the correct ways to do it?
In ContinueWith
do this:
if (ca.Exception != null)
{
var ignoreTask = Task.Run(() => _logger.LogException(LogLevel.Error, ca.Exception.Message, ca.Exception));
}
You are kicking off a new task on a thread pool thread and not awaiting the task. Place the LogException
code block in a try
/catch
block to ignore any exception raised.