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