关闭活动线程超过误差阈值后



我有一个应用程序,该应用程序将旋转线程列表,然后将它们接一个地踢开,直到达到预定义的线程限制,一旦发生这种情况,它将等到线程完成在开始另一个之前。我想实现一种方法,以退出当前正在运行的所有线程,如果达到连续错误的阈值。我已经清除了要处理的线程列表,因此将不再启动,但是我不确定如何关闭一旦达到线程限制的剩余线程,我都知道一个线程可以't与另一个人交谈,这就是我被挂断的地方..我提供了下面的主要方法。

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();
        }

假设您不介意杀死线程(通常不是一个好主意),则可以在清除列表之前使用类似的代码:

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

话虽如此,如果您相信此海报:

,您可能不应该使用thread.abort()

您是否读过MSDN上的"备注"部分?切勿使用中断。它是最后的度假胜地。如果您使用线程。射击,天空可能会掉下来,小猫将被杀死

无论您选择哪种方法,都可以将其放入ForEach表达式中,例如如果您喜欢使用Interrupt

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

另一种(更简单)的方法是修改线程以检查全局标志变量并在设置时干净地退出。在您的主要程序中,当您希望杀死线程时,只需设置标志即可。确保使用挥发性变量,或者更好,或者更好。

最新更新