一旦超过错误阈值,关闭活动线程

时间:2017-02-21 22:51:08

标签: c# multithreading

我有一个应用程序,它会启动一个线程列表,然后一个接一个地启动它们直到达到预定义的线程限制,一旦发生这种情况,它将等到一个线程完成后再启动另一个。我想实现一种方法来退出当前正在运行的所有线程,如果达到连续错误的阈值。我已经清除了要处理的线程列表,所以不会再启动但是我不确定如何在达到线程限制后关闭正在运行的剩余线程,我认识到一个线程可以和别人说话,那就是我被挂断的地方..我已经提供了以下主要方法的缩减版本。

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

        }

1 个答案:

答案 0 :(得分:-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上的“评论”部分?永远不要使用中止。它是最后的度假村。如果你使用线程。天空,天空可能会下降,而小猫会被杀死

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

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

另一种(更简单的)方法是修改线程以检查全局标志变量,并在设置时干净地退出。在你的主程序中,当你想杀死线程时,只需设置标志即可。请务必使用volatile变量,或者更好的是WaitHandle