2017-09-06 1 views
0

私はASP.NET Web APIを開発しています。コントローラのアクションの1つでTask.Factory.StartNew呼び出しを使用します。Task.Factory.StartNewを使用してExceptionFilterAttributeがトリガーされない

ただし、タスク内で例外がスローされたときに設定した例外フィルタはトリガされません。

Controller.cs

public class MyController : ApiController 
{ 
    [HttpPost] 
    public HttpResponseMessage Post() 
    { 
     Task.Factory 
      .StartNew(() => DoTheThing()) 
      .ContinueWith(tsk => { throw new Exception("Webhook Exception", tsk.Exception); }, TaskContinuationOptions.OnlyOnFaulted); 

     return new HttpResponseMessage(HttpStatusCode.OK); 
    } 
} 

ExceptionFilter.cs

public class ExceptionFilter : ExceptionFilterAttribute 
{ 
    public override void OnException(HttpActionExecutedContext context) 
    { 
     throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError) 
     { 
      Content = new ObjectContent(typeof(object), new 
      { 
       Message = "Critical Error", 
       ExceptionMessage = "An error occurred, please try again or contact the administrator.", 
       Type = ExceptionType.Unhandled 
      }, new JsonMediaTypeFormatter()), 
      ReasonPhrase = "Critical Error" 
     }); 
    } 
} 

Global.asax.cs

public class MyApplication : HttpApplication 
{ 
    protected void Application_Start() 
    {    
     GlobalConfiguration.Configuration.Filters.Add(new ExceptionFilter()); 
    } 
} 

Iデバッグでき、ContinueWithメソッドがトリガされ、新しいExceptionがスローされます。しかし、フィルターはトリガーされません。

+0

あなたは(再)「例外」を観察しているわけではないので、「観察されない例外」です。参照:[.NET 4.5のタスク例外処理](https://blogs.msdn.microsoft.com/pfxteam/2011/09/28/task-exception-handling-in-net-4-5/) – IronGeek

+0

ありがとうリンク、私は今問題を理解すると思います。私はフィルタが自分のアクションで例外をキャッチするので、私は不可能にしようとしています。しかし私は自分の仕事が終わる直前に私の行動が戻るようにしたい。 – Joe

答えて

2

コントローラのアクションメソッドのスレッドとは異なるスレッドで例外がスローされるため、フィルタはトリガされません。あなたは可能性:

  1. 待つタスク

    [HttpPost] 
    public async Task<HttpResponseMessage> Post() 
    { 
        await Task.Factory 
         .StartNew(() => DoTheThing()) 
         .ContinueWith(tsk => { throw new Exception("Webhook Exception", tsk.Exception); }, TaskContinuationOptions.OnlyOnFaulted); 
    
        return new HttpResponseMessage(HttpStatusCode.OK); 
    } 
    
  2. は、これらのアプローチの全ては、アクションメソッドで例外を再スローし、フィルターがそれをキャッチし、タスク

    [HttpPost] 
    public HttpResponseMessage Post() 
    { 
        var task = Task.Factory 
            .StartNew(() => DoTheThing()) 
            .ContinueWith(tsk => { throw new Exception("Webhook Exception", tsk.Exception); }, TaskContinuationOptions.OnlyOnFaulted); 
    
        task.Wait(); 
    
        return new HttpResponseMessage(HttpStatusCode.OK); 
    } 
    

を待ちます。

+0

私の質問に答えて正しいと印を付ける。すぐに私の行動から復帰し、タスクが完了するのを待たずに、私が望む解決策ではありません。しかし、これはコントローラアクションスレッド内で例外を捕捉するだけのフィルタの設計と矛盾していることが分かりました。 – Joe

+0

実際、例外フィルタはすべての例外をキャッチしますが、タスクはそれ自身のスレッドでそれらを処理します。とにかく、アクションメソッドからすぐに 'HttpStatusCode.OK'を返しますが、別のステータス - 'InternalServerError'をフィルタから返します。ただし、要求はすでに処理されており、クライアントは応答を受けています。アクションからの復帰後に継続タスクで例外を記録できますが、応答ステータスは書き換えられません。 –

関連する問題