在我的应用程序中,我有6个数组,代表我的应用程序执行的6个作业。每个作业基本上都与数据库交互并填充数组的每个元素。
我做的是创建6个线程并使6个数组全局,以便线程可以填充它们。我还创建了一个包含6个bool元素的数组(ThreadsAlive)。当一个线程完成它的执行时,它在bool数组中设置一个标志。我创建了一个作业监视器线程(threadwatcher)来监视这个bool线程。当该数组中的所有元素都设置为false时,我将确保我的作业已完成。
现在,问题是,由于Oledb驱动程序中的一些错误,ExecuteReader()语句卡在某个线程中并且永远不会恢复,我的应用程序将永远继续。实际上,可以“解决”错误可以重新启动该特定作业。下次该工作可能成功运行
我的计划是将所有6个线程作为Fields并与ThreadsAlive数组一起使用,我还将维护DateTime的LastActivityOfThreads数组。
所有作业线程将在执行查询时更新该数组中的时间。现在我的jobwatcher线程将监视任何线程的Last活动时间是否超过3分钟前。如果发生这种情况,它将终止该线程并且重启它。
只是想知道如何在不引发异常的情况下杀死任何线程。
更新:我这样做了,它显示“线程被中止”的异常
更新:也许我为每个操作使用单独的进程(exe),并且在主应用程序中不断监视进程。如果进程需要比平时更长的时间,我将终止该进程并重新启动它。
但在这种情况下,运行的6个进程将如何为我提供6个数组的数据?
更新:有可能在汇集时,如果我发现任何线程被暂停,我将使用
th =新线程(Fun_Name)并将旧线程放在原处。
答案 0 :(得分:1)
哎呀......我担心那辆有缺陷的OLEDB驱动程序会非常非常难以解决。你杀死线程的策略(可能是通过Thread.Abort
)可能是危险的,因为它可能会破坏应用程序域和可能的进程。您有时可以通过将行为不当的代码放在新的AppDomain
中然后中止在该应用程序域中卡住的线程来隔离这些问题,但是没有保证它会起作用并且不会使进程处于损坏状态。这里唯一安全的选择是将调用OLEDB驱动程序的代码放入一个单独的进程中。但是,这意味着您必须创建用于进行进程间通信的所有管道。它肯定会有更多的工作,但它仍然可以管理。
答案 1 :(得分:0)
如果不引发异常,您无法立即终止线程。它的设计旨在确保一致的资源锁定。如果某个布尔标志(比如_should_stop)为真,你可以为每个线程编写一个方法来阻止它。
答案 2 :(得分:0)
您可以使用事件等待句柄类(如自动复位事件或手动重置事件)来通知其他线程。在这种情况下,您不需要维护bool变量。您还可以指定线程操作的超时。如果事件未在指定的超时内设置,则可以假设存在一些异常。
中解释的线程同步概念答案 3 :(得分:0)
我认为您可能会发现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驱动程序中的这个“bug”是什么,并找到一种方法来避免它,或者更可能的事件,确保你没有做错任何事。