Search code examples
c#.netwcfexceptiontask

WCF Fire and forget exception handling


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?


Solution

  • 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.