OWIN SelfHost Web Api - Request Cancellation - How is it done? Thread aborts? OWIN SelfHost Web Api - Request Cancellation - How is it done? Thread aborts? multithreading multithreading

OWIN SelfHost Web Api - Request Cancellation - How is it done? Thread aborts?


I've dealt with this by handing the System.OperationCanceledException in a custom middleware I've registered before WebApi.

public class ExceptionHanldingMiddleware : OwinMiddleware{    public override async Task Invoke(IOwinContext context)    {        try        {            await Next.Invoke(context);        }        catch (OperationCanceledException) when (context.Request.CallCancelled.IsCancellationRequested)        {            //swallow user-agent cancelling request.            _log.Trace($"client disconnected on request for: {context.Request.Path}.");        }        catch (Exception ex)        {            _log.Error(ex);            context.Response.StatusCode = (int) HttpStatusCode.InternalServerError;            context.Response.ReasonPhrase = "Internal Server Error";        }    }   }


As you stated that your async controller is awaiting for a Task, which sometimes got some exception, I suggest you ContinueWith extension method for a task, which can be run only then your task is faulted, like this:

task.ContinueWith(       t =>       logger.Error(t.Exception.Message, t.Exception);       , TaskContinuationOptions.OnlyOnFaulted);

This is a default mechanism to handle the exceptions, and this will work in OWIN application.

Second, as for the cancellation: task can be started with a CancellationToken structure, which can be used for a cancelling the task during the execution. You can read more in the MSDN article.

HttpResponse.ClientDisconnectedToken is used for a situation when the client has been disconnected and the request should not be proceed in execution.

You can use this token, or create your own with CancellationTokenSource, like this:

var source = new CancellationTokenSource();var token = source.Token;var task = Task.Factory.StartNew(() =>{    // Were we already canceled?    ct.ThrowIfCancellationRequested();    var moreToDo = true;    while (moreToDo)    {        // Poll on this property if you have to do         // other cleanup before throwing.         if (ct.IsCancellationRequested)        {            // Clean up here, then...            ct.ThrowIfCancellationRequested();        }    }}, token);