QTAgent32.exe,未处理的异常,通过Watson报告:System.NullReferenceException。

3

我目前正在尝试使用MSTest.exe为多线程功能创建单元测试。 当我运行测试时,这里是我得到的错误:

A first chance exception of type 'System.NullReferenceException' occurred in ApplicationManagement.exe
The thread 'Agent: adapter run thread for test 'UpdateDirectoryExceptionTest' with id 'a78d3e8e-e859-43aa-87aa-cf006f736dee'' (0x1150) has exited with code 0 (0x0).
The thread '<No Name>' (0x1bec) has exited with code 0 (0x0).
E, 6788, 86, 2011/10/20, 14:02:36.771, WKSTVMC0006\QTAgent32.exe, Unhandled Exception Caught, reporting through Watson: System.NullReferenceException: Object reference not set to an instance of an object.
   at CommonObjects4.clsThread.StartThreadMethod.Execute() in D:\DevProjects\CommonObjects4\classes\clsThread.cs:line 23
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.runTryCode(Object userData)
   at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   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()
The program '[6788] QTAgent32.exe: Managed (v4.0.30319)' has exited with code -2 (0xfffffffe).
The program '[1120] ApplicationManagement.vshost.exe: Managed (v4.0.30319)' has exited with code 0 (0x0).

如果我在Visual Studio中单独运行UpdateDirectoryExceptionTest,它会顺利通过,但是当我运行整个单元测试套件时,我会收到上述错误。以下是我最近开始测试的函数,我认为它与这个错误有关:

    public Thread StartClassThread(ref Thread ThreadObject, ThreadMethod MethodObject)
    {
        System.Threading.Thread startClassThreadReturn = null;
        try
        {
            if (ThreadObject == null && MethodObject == null)
            {
                throw new ApplicationException("Cannot have both ThreadObject and MethodObject as null parameters in call to StartClassThread.");
            }
            StartThreadMethod objMethod = new StartThreadMethod();
            objMethod.objThreadMethod = MethodObject;
            if (!(ThreadObject == null))
            {
                if (ThreadObject.ThreadState != System.Threading.ThreadState.Stopped)
                {
                    // Do nothing
                }
            }
            if (!(ThreadObject == null))
            {
                if (ThreadObject.ThreadState == System.Threading.ThreadState.Stopped 
                    | ThreadObject.ThreadState == System.Threading.ThreadState.Aborted
                    | ThreadObject.ThreadState == System.Threading.ThreadState.Unstarted) 
                { 
                    ThreadObject = null; 
                    ThreadObject = new Thread( new System.Threading.ThreadStart( objMethod.Execute ) ); 
                    ThreadObject.Start(); 
                } 
            } 
            else 
            { 
                ThreadObject = new Thread( new System.Threading.ThreadStart( objMethod.Execute ) ); 
                ThreadObject.Start(); 
            } 
            return ThreadObject; 
        } 
        catch (Exception excException) 
        { 
            ZEGApp.clsMain.objApplicationAudit.AuditMethodError(excException, System.Reflection.MethodInfo.GetCurrentMethod().DeclaringType.FullName + "." + System.Reflection.MethodBase.GetCurrentMethod().Name + " - " + excException.StackTrace);
        }
        finally 
        { 
            // Do nothing
        } 
        return startClassThreadReturn;
    } 

这是我从CruiseControl.NET获得的输出结果,与在Visual Studio中进行测试不同:
  <message>Passed                UnitTests.clsThreadTest.StartClassThreadTest2</message>
  <message>Process 'QTAgent32' [PID 3932] has finished profiling.</message>
  <message>Process 'QTAgent32' [PID 5388] has begun profiling.</message>
  <message>Error                 UnitTests.clsUltraCalendarTest.clsUltraCalendarConstructorTest</message>

请问有没有任何想法可以解决这些错误?谢谢。

更新:这是clsThread.cs的完整源代码(请注意,第23行是objThreadMethod();):

namespace CommonObjects4
{
    public class clsThread
    {

    #region '" Sub Class "'

    public delegate void ThreadMethod();

    private class StartThreadMethod  
    { 
        public ThreadMethod objThreadMethod; 
        public void Execute() 
        { 
            objThreadMethod(); // this is line 23
        }
    }

    #endregion

    #region '" Enumerator Declaration "'
    #endregion

    #region '" Variable Declaration "'
    #endregion

    #region '" Property Declaration "'
    #endregion

    #region '" Function Declaration "'

    public Thread StartClassThread(Thread ThreadObject, ThreadMethod MethodObject)
    {
        System.Threading.Thread startClassThreadReturn = null;
        try
        {
            if (ThreadObject == null && MethodObject == null)
            {
                throw new ApplicationException("Cannot have both ThreadObject and MethodObject as null parameters in call to StartClassThread.");
            }
            StartThreadMethod objMethod = new StartThreadMethod();
            objMethod.objThreadMethod = MethodObject;
            if (!(ThreadObject == null))
            {
                if (ThreadObject.ThreadState != System.Threading.ThreadState.Stopped)
                {
                    // Do nothing
                }
            }
            if (!(ThreadObject == null))
            {
                if (ThreadObject.ThreadState == System.Threading.ThreadState.Stopped | ThreadObject.ThreadState == System.Threading.ThreadState.Aborted ) 
                { 
                    ThreadObject = null; 
                    ThreadObject = new Thread( new System.Threading.ThreadStart( objMethod.Execute ) ); 
                    ThreadObject.Start(); 
                } 
            } 
            else 
            { 
                ThreadObject = new Thread( new System.Threading.ThreadStart( objMethod.Execute ) ); 
                ThreadObject.Start(); 
            } 
            return ThreadObject; 
        } 
        catch (Exception excException) 
        { 
            ZEGApp.clsMain.objApplicationAudit.AuditMethodError(excException, System.Reflection.MethodInfo.GetCurrentMethod().DeclaringType.FullName + "." + System.Reflection.MethodBase.GetCurrentMethod().Name + " - " + excException.StackTrace);
        }
        finally 
        { 
            // Do nothing
        } 
        return startClassThreadReturn;
    } 

    #endregion 

} 
}

1
D:\DevProjects\CommonObjects4\classes\clsThread.cs的第23行是什么?如果您能添加完整的StartThreadMethod.Execute()方法主体或者更好的是完整的StartThreadMethod类定义,这可能会有所帮助。 - Nicole Calinoiu
谢谢你的建议,Nicole。请查看上面的clsThread.cs代码。 - user8128167
2个回答

3
第23行出现了问题,看起来是因为objThreadMethod为空。语法objThreadMethod()实际上是objThreadMethod.Invoke()的简写,因此如果在执行该行时objThreadMethod为空,将会得到一个NullReferenceException
至于为什么它为空,我猜测你已经使用非空的ThreadObject和空的MethodObject调用了StartClassThread方法,这导致在将objMethod.objThreadMethod设置为空MethodObject后执行了以下块:
ThreadObject = null;
ThreadObject = new Thread( new System.Threading.ThreadStart( objMethod.Execute ) );
ThreadObject.Start();

是的,我正在编写的测试之一明确地发送了一个空值以确保它正确处理。异常不应该被“catch(Exception excException)”代码捕获,而不是导致整个单元测试套件突然和过早地终止吗? - user8128167
1
异常不会自动在线程之间传播。异常在捕获块中所在的线程与发生异常的线程是分离的。如果您希望在生成的后台线程中捕获和记录异常,则需要在StartThreadMethod.Execute()方法中添加一个包装的try/catch。否则,后台线程上的异常将使您的进程崩溃。(话虽如此,我并不一定认为通常防止后台线程上未处理的异常导致进程崩溃通常是最好的想法。) - Nicole Calinoiu

1

谢谢你的建议,但是在添加了 <ExecutionThread apartmentState="MTA" /> 后,它仍然在同一点崩溃。它运行了 360 个测试中的 375 个,然后其余的测试失败了。如果我去掉线程单元测试,那么所有的测试都通过了。嗯... - user8128167

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接