繁体   English   中英

线程监控C#

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM