简体   繁体   English

线程监控C#

[英]Thread Monitoring C#

In my application I have 6 arrays which represents 6 jobs that my application performs.Each job is basically interacting with database and filling each element of array. 在我的应用程序中,我有6个数组,代表了我的应用程序执行的6个工作。每个工作基本上都是与数据库进行交互并填充数组的每个元素。
What I did is create 6 threads and make the 6 arrays global so that the threads can fill them.I have also created a array of 6 bool elements(ThreadsAlive).When a thread finishes it's execution, it sets a flag in the bool array.I created a job watcher thread(threadwatcher) to monitor this bool thread.When all the elements in that array are set to false, i will be sure that my jobs are completed. 我要做的是创建6个线程并全局设置6个数组,以便线程可以填充它们。我还创建了一个6个布尔元素的数组(ThreadsAlive)。当线程完成执行时,它将在bool数组中设置一个标志我创建了一个作业监视线程(threadwatcher)来监视这个布尔线程。当该数组中的所有元素都设置为false时,我将确保作业已完成。

Now, the problem is that, due to some bug in Oledb driver, the ExecuteReader() statement stucks in some thread and never recover and my application continues forever.Actually the bug can be "resolved" can restarting that particular job.Next time that job may run successfully. 现在的问题是,由于Oledb驱动程序中的某些错误,ExecuteReader()语句卡在某个线程中,并且永远无法恢复,并且我的应用程序将永远继续运行。实际上,该错误可以“解决”,可以重新启动该特定作业。作业可能成功运行。
What my plan is that I will make all the 6 threads as Fields and along with the ThreadsAlive array, i will also maintain a LastActivityOfThreads array of DateTime. 我的计划是将所有6个线程都作为Fields并与ThreadsAlive数组一起使用,我还将维护DateTime的LastActivityOfThreads数组。
All the job threads will update the time in that array when they execute a query.Now my jobwatcher thread will monitor if the Last activity time of any thread is more than, say 3 min ago.If that happens, it will kill that thread and restart it. 所有作业线程在执行查询时都会更新该数组中的时间。现在,我的作业观察者线程将监视任何线程的上次活动时间是否超过例如3分钟前,如果发生,它将杀死该线程并重新启动它。

Just wanted to know how can I kill any thread without raising an exception. 只是想知道如何在不引发异常的情况下杀死任何线程。

Update:I did that and it's showing exception that "Thread was being aborted" 更新:我做到了,并且显示了“线程被中止”的异常

Update:Maybe I use seperate process(exe) for each operation and in the main application constantly monitor the processes.If a process will take longer than usual, I will just kill the process and restart it. 更新:也许我对每个操作使用单独的进程(exe),并且在主应用程序中不断监视进程。如果一个进程比平时花费更长的时间,我将杀死该进程并重新启动它。
But in this case how will the 6 processes running will give me the data of 6 arrays ? 但是在这种情况下,运行的6个进程将如何给我6个数组的数据?

Update:Is it possible that while pooling, if i find any thread suspended, i will use 更新:是否有可能在池化期间,如果我发现任何线程挂起,我将使用
th = new Thread(Fun_Name) and let the old thread where it was. th = new Thread(Fun_Name)并将旧线程放回原处。

Ouch...that buggy OLEDB driver is going to be very hard to workaround I am afraid. 哎哟......那车OLEDB驱动程序将是非常困难的解决办法,我害怕。 Your strategy of killing the thread (presumably via Thread.Abort ) could be dangerous since it could corrupt the app domain and possibly the process. 您杀死线程的策略(可能是通过Thread.Abort )可能很危险,因为它可能破坏应用程序域和进程。 You can sometimes isolate these problems by placing the misbehaving code in a new AppDomain and then aborting the thread that gets stuck in that app domain, but there are no guarentees that it will work and not leave the process in a corrupted state. 您有时可以通过将行为异常的代码放在新的AppDomain ,然后中止陷入该应用程序域的线程来隔离这些问题,但是没有保证它将起作用并且不会使进程处于损坏状态。 Your only safe bet here is place the code calling the OLEDB driver into a separate process. 您唯一安全的选择是将调用OLEDB驱动程序的代码放在单独的进程中。 But, that means you will have to create all of the plumbing for doing inter-process communication. 但是,这意味着您必须创建所有用于进行进程间通信的管道。 Its definitely a lot more work, but it is still manageable. 它肯定还有很多工作,但是仍然可以管理。

You cannot instantly terminate a thread without raising an exception. 您不能在不引发异常的情况下立即终止线程。 It has been designed so to ensure consistent resource locking. 其设计旨在确保一致的资源锁定。 What you can do is write a method for each thread to stop it if some boolean flag (say _should_stop) is true. 您可以做的是为每个线程编写一个方法,以在某个布尔标志(例如_should_stop)为true时将其停止。

You can use the Event Wait Handle classes like autoreset event or manual reset events to notify other threads. 您可以使用事件等待句柄类(例如自动重置事件或手动重置事件)来通知其他线程。 You would not need to maintain the bool variables in that case. 在这种情况下,您将不需要维护布尔变量。 You can also specify the timeout for the thread operation. 您还可以指定线程操作的超时。 If the event does not get set within a specified timeout you can assume there is some exception. 如果未在指定的超时时间内设置事件,则可以假定存在一些异常。

Have a look at thread synchronization concepts explained in a very nice book http://www.albahari.com/threading/ 看一本非常不错的书http://www.albahari.com/threading/中介绍的线程同步概念

I think you might find the CountDownLatch very useful: 我认为您可能会发现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();
    }
}

And here is a rough example of how you would use it: 这是如何使用它的一个粗略示例:

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();

Finally: 最后:

Now, the problem is that, due to some bug in Oledb driver, the ExecuteReader() statement stucks in some thread and never recover and my application continues forever. 现在,问题在于,由于Oledb驱动程序中的某些错误,ExecuteReader()语句卡在了某个线程中,并且永远无法恢复,并且我的应用程序将永远继续运行。

I think you need to figure out what is this "bug" in the Oledb driver and find a way to avoid it or, the more likely event, ensure that you're not doing anything wrong. 我认为您需要弄清楚Oledb驱动程序中的“错误”是什么,并找到避免该错误的方法,或者更有可能的是,确保您没有做任何错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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