2017-02-21 57 views
-1

我有一個應用程序將啓動一個線程列表,然後將它們一個接一個地踢出去,直到預定義的線程限制已被命中,一旦發生這種情況,它將一直等到一個線程在開始之前已經完成了。我想實現一種方式來退出當前正在運行的所有線程,如果達到連續錯誤的閾值。我已經清理了要處理的線程列表,所以不會再開始,但是我不知道如何在線程限制到達後關閉正在運行的其餘線程,我認識到一個線程可以與另一個人談話,這就是我被掛斷的地方..我提供了一個主要方法的簡化版本。一旦超出錯誤閾值,關閉活動線程

public static void Run(string distinguishedName, string hrExtractFile, string sanctionsFileLocation, string exemptionsFileLocation, string url, string soapAction, int threadLimit) 
     { 

      UsersList Employees = new UsersList(distinguishedName, hrExtractFile); //imports users from HR file 
      int errorcount = 0; 

      ManualResetEvent resetEventThreadComplete = new ManualResetEvent(false); 
      ManualResetEvent resetEventNoMoreThreads = new ManualResetEvent(false); 
      List<Thread> threads = new List<Thread>(); 
      int toProcess = Employees.Count; 

      for (int i = 0; i < Employees.Count; i++) 
      { 
       int current = i; 
       threads.Add(new Thread(delegate() 
       { 
        User u = Employees[current]; 
        User drUser = new User(); 

        try 
        { 
         drUser = fetchUser(u, url, soapAction); 
         bool userExists = false; 

         if (drUser != null) 
         { 
          userExists = true; 
         } 


         //removes a user if they're in the deleted users OU as well as being in system 
         if (u.IsDeleted) 
         { 
          if (userExists == true) 
          { 
           Console.WriteLine("Removing " + u.AccountName); 
           Log.writeToLogs("activitylog.txt", "Removing " + u.AccountName + ":", u, drUser); 
           DeleteUser(u, url, soapAction); 

          } 

         } 
          errorcount = 0; 
         } 


        } 

        catch (Exception e) 
        { 
         if (errorcount <= 5) 
         { 
          Log.writeToLogs("syslog.txt", e.ToString()); 
          Log.writeToLogs("activitylog.txt", u.AccountName + " - Failed to true up!"); 
          Console.WriteLine("Failed on " + u.AccountName + ": An error occured, check logs for details"); 
          errorcount++; 
         } 
         else 
         { 
          lock (_syncObject) 
          { 
           //removes threads from list of threads that are pending 
           if (threads.Count > 0) 
           { 
            threads.Clear(); 
           } 
          } 
         } 

        } 

        resetEventThreadComplete.Set(); 

        if (Interlocked.Decrement(ref toProcess) == 0) 
         resetEventNoMoreThreads.Set(); 

       })); 
      } 


      /* 
      * Kicks off the first x number of threads (where x = threadLimit) and removes them from list of pending threads 
      */ 
      for (int i = 0; i < threadLimit; i++) 
      { 
       if (threads.Count < 1) 
        break; 
       //runningThreads++; 
       threads[0].Start(); 
       threads.RemoveAt(0); 
      } 

      /* 
      *Controls the initiation of thread exection; When one thread finishes, another will be started and removed from the list of pending threads 
      */ 
      while (threads.Count > 0) 
      { 
       resetEventThreadComplete.WaitOne(); 
       resetEventThreadComplete.Reset(); 
       threads[0].Start(); 
       threads.RemoveAt(0); 
      } 

      if (toProcess > 0) resetEventNoMoreThreads.WaitOne(); 

      //Log.sendLogs(); 

     } 
+0

爲什麼這是一個asp.net標記? – VMAtm

+0

你說,「我認識到一個線程不能與另一個線程交談」,但這正是你需要做的,以便線程可以知道何時自然退出。 – Enigmativity

+0

對不起,多線程的經驗有限。我認爲我的意思是一個子線程不能直接訪問另一個子線程,他們需要改變其範圍之外的某些東西來指示其他需要發生的事情 - 是否正確? – Muz

回答

-2

假設你不介意殺死你的線程(通常不是一個好主意),你可以使用像這樣的代碼,只需清除列表前:

if (threads.Count > 0) 
{ 
    threads.ForEach(t => t.Abort()); //Kill all threads 
    threads.Clear(); 
} 

話雖這麼說,you should probably not use Thread.Abort() ,如果您確信this poster

您是否閱讀過MSDN上的「備註」部分?永遠不要使用中止。它的目的是作爲最後的度假村。如果你使用Thread.Abort的,SKY可能會掉下來,小貓就會被殺死

無論採用哪種方式,你可以把它變成ForEach表達,例如如果你喜歡使用Interrupt

threads.ForEach(t => t.Interrupt()); 

另一個(更簡單)方法是修改你的線程乾淨地檢查全局標誌變量和退出時,它被設置。在你的主程序中,當你想殺死線程時,只需設置標誌。請務必使用volatile變量,或者更好的是使用WaitHandle

+0

謝謝!我是否認爲我不能從打出錯誤閾值的線程調用它?我想也許使用一個全局布爾值,它在運行時不斷檢查,如果它改變了,線程就會按照你所鏈接的文章中的建議關閉。 – Muz

+1

可能更好地管理列表中不在列表中的線程。否則,代碼可能會最終中止自己! –

+1

不,不,不!永遠不要調用'Thread.Abort()'。它可以很容易地破壞.NET運行時。它應該只在你想強制整個應用程序關閉時才使用。 – Enigmativity