处理Hangfire内部的异常

时间:2017-03-21 10:35:56

标签: asp.net-core asp.net-core-1.0 hangfire

我有一个场景,我正在安排一个BackgroundJob在应用程序启动后的一些随机秒后运行。执行作业后,我再次安排相同的BackgroundJob在一些随机秒后运行,然后继续运行并且永不停止。

我想要的是如果在这个连续过程中Hangfire发生任何异常,我想关闭我的asp.net核心应用程序。

例如,当这个过程发生时,我停止了SQL Server。所以hangfire给出了这个明显的异常

  

System.Data.SqlClient.SqlException:建立与SQL Server的连接时发生与网络相关或特定于实例的错误。服务器未找到或无法访问。验证实例名称是否正确,以及SQL Server是否配置为允许远程连接。 (提供者:命名管道提供程序,错误:40 - 无法打开与SQL Server的连接)

     

System.ComponentModel.Win32Exception:系统找不到指定的文件
  ---内部异常堆栈跟踪结束---
  在System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject,UInt32 waitForMultipleObjectsTimeout,Boolean allowCreate,Boolean onlyOneCheckConnection,DbConnectionOptions userOptions,DbConnectionInternal& connection)       在System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject,TaskCompletionSource1 retry,DbConnectionOptions userOptions,DbConnectionInternal& connection)       在System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection,TaskCompletionSource1 retry,DbConnectionOptions userOptions,DbConnectionInternal oldConnection,DbConnectionInternal& connection)       在System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection,DbConnectionFactory connectionFactory,TaskCompletionSource1 retry,DbConnectionOptions userOptions)       在System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource1重试)       在System.Data.SqlClient.SqlConnection.Open()       在Hangfire.SqlServer.SqlServerStorage.CreateAndOpenConnection()       在Hangfire.SqlServer.SqlServerStorage.UseConnection [T](Func`2 func)       在Hangfire.SqlServer.SqlServerConnection.RemoveTimedOutServers(TimeSpan timeOut)       在Hangfire.Server.ServerWatchdog.Execute(BackgroundProcessContext context)       在Hangfire.Server.AutomaticRetryProcess.Execute(BackgroundProcessContext context)

所以我不知道在哪里处理此异常,以便在发生此异常时我可以停止我的应用程序。

3 个答案:

答案 0 :(得分:1)

我认为你有两个选择:

    您使用Hangfire调用的方法中的
  1. try catch
  2. 使用IElectStateFilter,特别是如果您希望对任何Hangfire作业具有相同的行为
  3. 第一个选项很简单:

    public void MyMethod() {
        try {
            //your code
        }
        catch(Exception ex) { 
            //stop application here
        }
    }
    
    BackgroundJob.Enqueue(() => MyMethod());
    

    第二个选项是这样的:

    1. 创建属性类:

      public class MyFilterAttribute : JobFilterAttribute, IServerFilter, IElectStateFilter 
      {
          public void OnStateElection(ElectStateContext context)
          {
              var failedState = context.CandidateState as FailedState;
              if (failedState != null)
              {
                  //job has failed, stop application here
              }
          }
      }
      
    2. 注册过滤器:

      GlobalConfiguration.Configuration.UseFilter(new MyFilterAttribute());
      
    3. 将属性添加到方法

      [MyFilter]
      public void MyMethod() {
          //your code
      }
      
    4. 照常调用您的代码:

      BackgroundJob.Enqueue(() => MyMethod());        
      
    5. 有关过滤器,请参阅documentation

答案 1 :(得分:0)

如果注册自定义IJobFilterProvider,则必须在GetFilters方法的结果中包含GlobalFilters.Filters。例如:

public virtual IEnumerable GetFilters(Job job)
{
    var result = GlobalJobFilters.Filters.AsEnumerable()
                 .Concat(new JobFilter[] {
                     new JobFilter(new QueueAttribute(GetQueueName(job)), 
                                   JobFilterScope.Method, null)
                 });
    return result;
}

这对我有用!

答案 2 :(得分:0)

我通过检查存储是否已连接到hangfire来解决了这个问题。

        try
        {
            IStorageConnection connection = JobStorage.Current.GetConnection();
            return true;
        }
        catch (Exception e)
        {
            return false;
        }