3

目前,我嘗試使用MSTest.exe創建單元測試以實現多線程功能。當我運行測試,下面是我得到的錯誤:QTAgent32.exe,捕獲未處理的異常,通過Watson進行報告:System.NullReferenceException

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> 

有沒有人有任何想法,我怎樣才能解決這些錯誤? TIA。

UPDATE:這裏是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類定義,這可能會有所幫助。) –

+0

感謝您的建議,Nicole。請參閱上面的clsThread.cs代碼。 – Roger

回答

3

的問題似乎是objThreadMethod是在第23行的語法objThreadMethod()空實際上是objThreadMethod.Invoke()簡寫,所以你會得到一個NullReferenceException如果執行行時objThreadMethod爲空。

至於爲什麼是空的,我猜你已經調用StartClassThread方法與非空ThreadObject和空MethodObject,這就造成了以下塊設置objMethod.objThreadMethod爲空MethodObject後執行:

ThreadObject = null; 
ThreadObject = new Thread(new System.Threading.ThreadStart(objMethod.Execute)); 
ThreadObject.Start(); 
+0

是的,我正在寫的測試之一是明確發送一個空值,以確保它正確處理它。不應該由「catch(Exception excException)」代碼捕獲異常,而不是讓整個單元測試套件突然和過早終止? – Roger

+1

異常不會在線程之間自動傳播。異常發生在與catch塊分離的線程中。如果你想在產生的後臺線程中捕獲和記錄異常,你需要在StartThreadMethod.Execute()方法中添加一個包裝try/catch。否則,後臺線程中的異常會導致您的進程中斷。 (也就是說,我不一定會認爲有系統地防止在後臺線程上出現未處理的異常,從而導致進程失敗通常是世界上最好的想法。) –

+0

好的,這是有道理的。謝謝! – Roger

1

我認爲,首先,你要配置的測試與多線程運行公寓:

http://msdn.microsoft.com/en-us/library/ms404663.aspx

我會嘗試,看看您是否繼續有例外。

+0

感謝提示,但是,在添加後,它仍然在同一點崩潰。它運行375次測試中的360次,然後測試的其餘部分失敗。如果我拿出線程單元測試,那麼所有的測試都會通過。嗯... – Roger

相關問題