簡體   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