简体   繁体   中英

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.
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.

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.
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.
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.

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.
But in this case how will the 6 processes running will give me the data of 6 arrays ?

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.

Ouch...that buggy OLEDB driver is going to be very hard to workaround I am afraid. Your strategy of killing the thread (presumably via Thread.Abort ) could be dangerous since it could corrupt the app domain and possibly the process. 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. Your only safe bet here is place the code calling the OLEDB driver into a separate process. 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.

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/

I think you might find the CountDownLatch very useful:

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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