C# 超过错误阈值后关闭活动线程
我有一个应用程序,它将启动一个线程列表,然后一个接一个地启动它们,直到达到预定义的线程限制,一旦发生这种情况,它将等待一个线程完成后再启动另一个线程。我想实现一种方法,在达到连续错误阈值时退出当前正在运行的所有线程。我已经清理了要处理的线程列表,因此不会再启动更多线程,但我不确定如何关闭线程限制达到后正在运行的剩余线程,我认识到一个线程无法与另一个线程对话,这就是我挂断的原因。我在下面提供了一个主方法的精简版本C# 超过错误阈值后关闭活动线程,c#,multithreading,C#,Multithreading,我有一个应用程序,它将启动一个线程列表,然后一个接一个地启动它们,直到达到预定义的线程限制,一旦发生这种情况,它将等待一个线程完成后再启动另一个线程。我想实现一种方法,在达到连续错误阈值时退出当前正在运行的所有线程。我已经清理了要处理的线程列表,因此不会再启动更多线程,但我不确定如何关闭线程限制达到后正在运行的剩余线程,我认识到一个线程无法与另一个线程对话,这就是我挂断的原因。我在下面提供了一个主方法的精简版本 public static void Run(string distinguishe
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();
}
publicstaticvoidrun(stringdistrignedname、stringhrextractfile、stringsanctionsfilelocation、stringexemptionsfilelocation、stringurl、stringsoapaction、int-threadLimit)
{
UsersList Employees=new UsersList(differentiedname,hrExtractFile);//从HR文件导入用户
int errorcount=0;
ManualResetEvent resetEventThreadComplete=新的ManualResetEvent(错误);
ManualResetEvent resetEventNoMoreThreads=新的ManualResetEvent(错误);
列表线程=新列表();
int toProcess=Employees.Count;
对于(int i=0;i0)
{
resetEventThreadComplete.WaitOne();
resetEventThreadComplete.Reset();
线程[0]。开始();
线程。移除(0);
}
如果(toProcess>0)resetEventNoMoreThreads.WaitOne();
//Log.sendLogs();
}
假设您不介意终止线程(通常不是一个好主意),您可以在清除列表之前使用以下代码:
if (threads.Count > 0)
{
threads.ForEach(t => t.Abort()); //Kill all threads
threads.Clear();
}
话虽如此,如果你相信:
您是否阅读了MSDN上的“备注”部分?永远不要使用中止。这是作为最后手段。如果您使用THREAD.ABORT,天空可能会倒下,小猫将被杀死
无论您选择何种方法,都可以将其放入ForEach
表达式中,例如,如果您喜欢使用中断
:
threads.ForEach(t => t.Interrupt());
另一种(简单得多)方法是修改线程以检查全局标志变量,并在设置该变量时干净地退出。在主程序中,当您希望终止线程时,只需设置标志。请确保使用变量,或者更好的是使用。为什么这是一个asp.net标记?您可以说,“我认识到一个线程无法与另一个线程通信”,但这正是您需要做的,以便线程能够知道何时自然退出。抱歉,多线程的经验有限。我想我的意思是一个子线程不能直接访问另一个子线程,他们将需要更改超出其范围的内容,以向另一方指示需要发生什么-这是否正确?堆栈溢出上已经有许多问题的答案,这些问题讨论了向线程发出正确和安全的信号以取消或以其他方式提前终止,包括标记的重复。注意,这方面的现代习惯用法包括使用
Task.Run()
创建后台工作程序,以及CancellationTokenSource
提供取消机制。如果你做得好,你甚至可以让你的任务
对象在提前终止时自动设置为取消状态(有助于各种原因,例如事后解决竞态问题)。谢谢!我认为我不能从达到错误阈值的线程调用它,对吗?我在想也许可以用一个全球布利亚