【问题标题】:Null reference exception in exception logging masking true error异常日志记录中的空引用异常掩盖了真正的错误
【发布时间】:2012-11-05 15:26:56
【问题描述】:

我们有一个由网络请求启动的长时间运行的进程。为了让进程有时间完成,我们在一个新线程上将其分离出来并使用互斥锁来确保只有一个进程实例可以运行。此代码在我们的开发和登台环境中按预期运行,但在我们的生产环境中失败并出现空引用异常。我们的应用程序日志没有捕获任何内容,我们的操作人员报告说它正在使 AppPool 崩溃。 (这似乎是一个环境问题,但我们必须继续假设环境配置相同。)到目前为止,我们无法确定 Null Reference 的位置。

以下是应用程序事件日志中的例外情况:

Exception: System.NullReferenceException
Message: Object reference not set to an instance of an object.
StackTrace:    at Jobs.LongRunningJob.DoWork()
   at System.Threading.ExecutionContext.runTryCode(Object userData)
   at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

这里是代码(稍微净化):

public class LongRunningJob: Job
{
    private static Mutex mutex = new Mutex();

    protected override void PerformRunJob()
    {
        var ts = new ThreadStart(LongRunningJob.DoWork);
        var thd = new Thread(ts);
        thd.IsBackground = true;
        thd.Start();
    }

    private static void DoWork()
    {
        var commandTimeOut = 180;

        var from = DateTime.Now.AddHours(-24);
        var to = DateTime.Now;

        if (mutex.WaitOne(TimeSpan.Zero))
        {
            try
            {
               DoSomethingExternal(); // from what we can tell, this is never called
            }
            catch (SqlException sqlEx)
            {
                if (sqlEx.InnerException.Message.Contains("timeout period elapsed"))
                {
                    Logging.LogException(String.Format("Command timeout in LongRunningJob: CommandTimeout: {0}", commandTimeOut), sqlEx);
                }
                else
                {
                    Logging.LogException(String.Format("SQL exception in LongRunningJob: {0}", sqlEx.InnerException.Message), sqlEx);
                }
            }
            catch (Exception ex)
            {
                Logging.LogException(String.Format("Error processing data in LongRunningJob: {0}", ex.InnerException.Message), ex);
            }
            finally
            {
                mutex.ReleaseMutex();
            }
        }
        else
        {
            Logging.LogMessage("LongRunningJob is already running.");
        }
    }
}

【问题讨论】:

  • 请不要在不适合它们的环境中执行长时间运行的进程,这只是最终催人泪下的开始:stackoverflow.com/a/5553048/263681
  • 感谢格兰特。我完全同意。
  • 我之前已经看到 ASP.NET 成功使用了 .NET 线程池。以下是如何启动请求并捕获它可能引发的任何异常:stackoverflow.com/a/753855/1429439
  • 原来空引用在我们的异常日志中,它掩盖了潜在的错误。第一个例外是在 DoSomethingExternal() 方法中,我们试图截断复制的表。这就是它在除生产环境之外的所有环境中都取得成功的原因。
  • 为什么不直接记录 ex.ToString()?

标签: c# asp.net multithreading iis-7 mutex


【解决方案1】:

为了找到NullReferenceException,您基本上要检查每个取消引用操作。我只能看到以下可疑的:

ex.InnerException.Message

你不能假设ex.InnerException 不为空。

【讨论】:

  • usr - 我相信你可能会有所收获。可能我们的异常日志记录正在抛出它自己的异常,这掩盖了原始问题。我们将探索这个选项。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-23
  • 2011-01-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多