线程监控C#

时间:2010-09-25 02:46:04

标签: c# multithreading

在我的应用程序中,我有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)并将旧线程放在原处。

4 个答案:

答案 0 :(得分:1)

哎呀......我担心那辆有缺陷的OLEDB驱动程序会非常非常难以解决。你杀死线程的策略(可能是通过Thread.Abort)可能是危险的,因为它可能会破坏应用程序域和可能的进程。您有时可以通过将行为不当的代码放在新的AppDomain中然后中止在该应用程序域中卡住的线程来隔离这些问题,但是没有保证它会起作用并且不会使进程处于损坏状态。这里唯一安全的选择是将调用OLEDB驱动程序的代码放入一个单独的进程中。但是,这意味着您必须创建用于进行进程间通信的所有管道。它肯定会有更多的工作,但它仍然可以管理。

答案 1 :(得分:0)

如果不引发异常,您无法立即终止线程。它的设计旨在确保一致的资源锁定。如果某个布尔标志(比如_should_stop)为真,你可以为每个线程编写一个方法来阻止它。

答案 2 :(得分:0)

您可以使用事件等待句柄类(如自动复位事件或手动重置事件)来通知其他线程。在这种情况下,您不需要维护bool变量。您还可以指定线程操作的超时。如果事件未在指定的超时内设置,则可以假设存在一些异常。

看一下非常好的书http://www.albahari.com/threading/

中解释的线程同步概念

答案 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”是什么,并找到一种方法来避免它,或者更可能的事件,确保你没有做错任何事。