[英]Thread Monitoring C#
在我的应用程序中,我有6个数组,代表了我的应用程序执行的6个工作。每个工作基本上都是与数据库进行交互并填充数组的每个元素。
我要做的是创建6个线程并全局设置6个数组,以便线程可以填充它们。我还创建了一个6个布尔元素的数组(ThreadsAlive)。当线程完成执行时,它将在bool数组中设置一个标志我创建了一个作业监视线程(threadwatcher)来监视这个布尔线程。当该数组中的所有元素都设置为false时,我将确保作业已完成。
现在的问题是,由于Oledb驱动程序中的某些错误,ExecuteReader()语句卡在某个线程中,并且永远无法恢复,并且我的应用程序将永远继续运行。实际上,该错误可以“解决”,可以重新启动该特定作业。作业可能成功运行。
我的计划是将所有6个线程都作为Fields并与ThreadsAlive数组一起使用,我还将维护DateTime的LastActivityOfThreads数组。
所有作业线程在执行查询时都会更新该数组中的时间。现在,我的作业观察者线程将监视任何线程的上次活动时间是否超过例如3分钟前,如果发生,它将杀死该线程并重新启动它。
只是想知道如何在不引发异常的情况下杀死任何线程。
更新:我做到了,并且显示了“线程被中止”的异常
更新:也许我对每个操作使用单独的进程(exe),并且在主应用程序中不断监视进程。如果一个进程比平时花费更长的时间,我将杀死该进程并重新启动它。
但是在这种情况下,运行的6个进程将如何给我6个数组的数据?
更新:是否有可能在池化期间,如果我发现任何线程挂起,我将使用
th = new Thread(Fun_Name)并将旧线程放回原处。
哎哟......那车OLEDB驱动程序将是非常困难的解决办法,我害怕。 您杀死线程的策略(可能是通过Thread.Abort
)可能很危险,因为它可能破坏应用程序域和进程。 您有时可以通过将行为异常的代码放在新的AppDomain
,然后中止陷入该应用程序域的线程来隔离这些问题,但是没有保证它将起作用并且不会使进程处于损坏状态。 您唯一安全的选择是将调用OLEDB驱动程序的代码放在单独的进程中。 但是,这意味着您必须创建所有用于进行进程间通信的管道。 它肯定还有很多工作,但是仍然可以管理。
您不能在不引发异常的情况下立即终止线程。 其设计旨在确保一致的资源锁定。 您可以做的是为每个线程编写一个方法,以在某个布尔标志(例如_should_stop)为true时将其停止。
您可以使用事件等待句柄类(例如自动重置事件或手动重置事件)来通知其他线程。 在这种情况下,您将不需要维护布尔变量。 您还可以指定线程操作的超时。 如果未在指定的超时时间内设置事件,则可以假定存在一些异常。
看一本非常不错的书http://www.albahari.com/threading/中介绍的线程同步概念
我认为您可能会发现CountDownLatch
非常有用:
public class CountDownLatch
{
private int m_remain;
private EventWaitHandle m_event;
public CountDownLatch(int count)
{
if (count < 0)
throw new ArgumentOutOfRangeException();
m_remain = count;
m_event = new ManualResetEvent(false);
if (m_remain == 0)
{
m_event.Set();
}
}
public void Signal()
{
// The last thread to signal also sets the event.
if (Interlocked.Decrement(ref m_remain) == 0)
m_event.Set();
}
public void Wait()
{
m_event.WaitOne();
}
}
这是如何使用它的一个粗略示例:
ManualResetEvent hasWork = new ManualResetEvent(false);
CountDownLatch countDown = new CountDownLatch(6);
List<Thread> threads = new List<Thread>();
volatile bool running = true;
int timeoutPeriod = 60 * 1000 * 3; // 3 minutes
for(int i = 0; i < 6; i++)
{
Thread t = new Thread(()=>
{
try
{
// Block till there is some work
hasWork.WaitOne();
while(running)
{
// Perform the work
PerformWork();
}
}
catch(InterruptException)
{
// Ignore if you're Interrupting the thread yourself
}
finally
{
// Signal you're done
countDown.Signal();
}
});
t.IsBackground = true;
t.Start();
threads.Add(t);
}
Thread workerKiller = new Thread(()=>
{
// If you need to kill your threads if they
// are working for too long, then you can
// setup a "worker killer" to kill them if
// some condition is met...
// In this case you give the threads a maximum
// of 3 minutes to complete the work and then
// you stop all of them.
Thread.Sleep(timeoutPeriod);
// Interrupt the threads
running = false;
foreach(Thread t in threads)
{
t.Interrupt();
}
});
workerKiller.IsBackground = true;
workerKiller.Start();
// Lift the barrier
hasWork.Set();
// Wait for all the threads to signal
// that they have completed their work.
countDown.Wait();
最后:
现在,问题在于,由于Oledb驱动程序中的某些错误,ExecuteReader()语句卡在了某个线程中,并且永远无法恢复,并且我的应用程序将永远继续运行。
我认为您需要弄清楚Oledb驱动程序中的“错误”是什么,并找到避免该错误的方法,或者更有可能的是,确保您没有做任何错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.