3

There are some tasks that I attached an action to. I have a middleware for observing all of the exceptions. Now, there is a problem with thread exception. I've already thrown an exception manually in body of the action, but when I throw an exception the application goes to break mode state and I can't monitor the exceptions.

Before mvc in configure, I put my error handling middleware

public class ErrorHandlingMiddleware
{
    private readonly RequestDelegate next;

    public ErrorHandlingMiddleware(RequestDelegate next)
    {
        this.next = next;
    }

    public async Task Invoke(HttpContext context /* other dependencies */)
    {
        try
        {
            await next(context);
        }
        catch (Exception ex)
        {
            await HandleExceptionAsync(context, ex);
        }
    }

    private static Task HandleExceptionAsync(HttpContext context, Exception exception)
    {
        var code = HttpStatusCode.InternalServerError; 

        var result = JsonConvert.SerializeObject(new { error = exception.Message });
        context.Response.ContentType = "application/json";
        context.Response.StatusCode = (int)code;
        return context.Response.WriteAsync(result);
    }
}
//and this is the piece of code that run all tasks. 
foreach (var item in BotList)
{
            BotHandler BotObject = new BotHandler(item,conn);
            Task.Run(() => { BotObject.Run();});
}      
//

  public void Run()
    {

        //BotClient.StopReceiving();
        BotClient.OnMessage += BotOnMessageReceived;
        BotClient.OnMessageEdited += BotOnMessageReceived;
        BotClient.OnCallbackQuery += BotOnCallbackQueryReceived;

    }
     private async void BotOnMessageReceived(object sender, MessageEventArgs messageEventArgs)
    {
       try
           {
              //do something
                string a = null;
                var b = a.ToString();
           }
       catch(Exception exp )
       {
         throw exp
       }
    }
}
svoychik
  • 1,188
  • 1
  • 8
  • 19
Mohsen Zahedi
  • 651
  • 2
  • 10
  • 28

2 Answers2

3

As I understood you run this code in action of controller:

//and this is the piece of code that run all tasks. 
foreach (var item in BotList)
{
            BotHandler BotObject = new BotHandler(item,conn);
            Task.Run(() => { BotObject.Run();});
}  

The main problem is that you are trying to run the task for an already finished request. That is why ExceptionHandlingMiddleware (and actually other middlewares) can't handle anything. To fix your issue you can add try/catch block to handle an unexpected exception.

I would strongly advise not to start a background task during an HTTP request. It's error-prone approach as a task may shut down at any time and you won't even notice. Instead of this approach, it's better to use background task (msdn, SO Discussion), some kind of AWS lambda/Azure function or another task scheduler.

In case you need to do some recalculation job after HTTP method is called you may consider async message processing to trigger the process.

svoychik
  • 1,188
  • 1
  • 8
  • 19
  • I use telegram bot and these tasks are for running bots because of that I have to use task for do that .could you please show me a better way by some code ? – Mohsen Zahedi Dec 31 '18 at 05:36
  • I used hangfire for running background job but I have the problem yet. – Mohsen Zahedi Dec 31 '18 at 07:19
  • @MohsenZahedi You have two ways: 1) write a console application with subscription usage like you already did. 2) use webhooks: create API methods for bots and register this HTTP method in platrform which you use. Most platforms support this approach – svoychik Dec 31 '18 at 10:07
2

if you go here https://msdn.microsoft.com/en-us/magazine/jj991977.aspx you will read that.

Exceptions from an Async Void Method Can’t Be Caught with Catch

So you cannot catch exception (the middleware cannot) which you are throwing in your BotOnMessageReceived method (in a Catch part).

So you have 2 solutions.

  1. Remove async keyword
  2. Or Catch app unhandled exceptions if its possible. For example in normal .net framework console app, you have event in App called unhandled exceptions, and can handle such situations like yours.

I have also found smth here, maybe it will help How do I catch unhandled exceptions in ASP .NET Core 2.0 before the page is rendered?

Paweł Górszczak
  • 524
  • 1
  • 5
  • 12
  • It's not only about async void: ExceptionHandlingMiddleware just can't handle exception because the request was finished so first proposed solution won't help him – svoychik Dec 30 '18 at 23:33