我試圖實現一個典型的線程應用程序,其中一個線程詢問設備是否有數據可用,將數據複製到其自己的內存並將數據發送到數據可用的主線程。主線程將數據複製到其自己的內存並將其顯示在GUI上。監視器和ReaderWriterLockSlim不起作用
爲此,我使用Visual Studio 2012和C++/CLI與Winforms。
有一個類「Work」,它包含線程方法「checkDataIsAvailable」。 「Work」類實現了一個接口(相當於一個抽象類),它具有一個作爲事件的代理「OnRetrievedData」,並在「Form1」中調用「BeginInvoke」以實現異步行爲。還有一個方法「getData」,其中主線程可以從「checkDataIsAvailable」線程獲取數據。此外,「Work」類嘗試從類「ValueGenerator」中獲取可能代表任何實際設備的數據。我在「Work」類中爲「數據」標識了一個稱爲「array^m_Data;」的關鍵部分。問題是「Monitor」和「ReaderWriterLockSlim」工作方法都無法正常工作。 使用「監視器」時,圖形用戶界面出現延遲響應,許多更新丟失。 使用「ReaderWriterLockSlim」,應用程序崩潰。 而不保存應用程序的關鍵部分。但我不知道原因,因爲我確信必須保存數據。
我想簡化源代碼並強調重要的東西。
最重要的是線程方法:
System::Void Work::checkDataIsAvailable()
{
while ((Thread::CurrentThread->ThreadState & Threading::ThreadState::Running) == Threading::ThreadState::Running)
{
m_WaitForDoCheckDataIsAvailableHandle->WaitOne();
//Monitor::Enter(m_LockData);
m_rwlock->EnterWriteLock();
m_Data = m_ValueGenerator->getData();
m_rwlock->ExitWriteLock();
//Monitor::Exit(m_LockData);
if (nullptr != OnRetrievedData)
{
OnRetrievedData();
}
}
}
這裏你可以看到從「ValueGenerator」給變量M_DATA複製過程。在我看來,這是一個關鍵部分。然後發送事件「OnRetrievedData」,數據可用。
此事件將得到Form1中:
System::Void Form1::OnAcquisitionUpdate()
{
if(this->InvokeRequired == true)
{
OnAcquisitionUpdateDelegate^ onAcquisitionUpdateDelegate = gcnew OnAcquisitionUpdateDelegate(this, &Form1::OnAcquisitionUpdate);
this->BeginInvoke(onAcquisitionUpdateDelegate);
//this->Invoke(onAcquisitionUpdateDelegate);
}
else
{
if (nullptr != m_Work)
{
//Thread::Sleep(5000);
array<System::Int32>^ data;
m_Work->getData(data);
dataResult_label->Text = data->Length.ToString();
}
}
}
「Form1中:: OnAcquisitionUpdate」 內經 「的BeginInvoke」 則切換到主線程,並呼籲再次 「Form1中:: OnAcquisitionUpdate」,但現在 「InvokeRequired」 是false,所以調用「Work」類來從主線程獲取數據。
System::Void Work::getData(array<System::Int32>^% data)
{
//Monitor::Enter(m_LockData);
m_rwlock->EnterReadLock();
Console::WriteLine(" getData() -> Data length = {0}", m_Data->Length);
data = m_Data;
m_rwlock->EnterReadLock();
//Monitor::Exit(m_LockData);
}
在這裏我看到數據將被複製爲調用方Form1的下一個關鍵部分。
這將是很好,如果有人可以幫助在這種情況下。
這是很多代碼。你能否簡化它,只有與你的問題實際相關的代碼才被包含在內?另外,應用程序究竟如何崩潰?如果您收到異常,它的消息和堆棧跟蹤是什麼? – svick 2013-04-27 20:37:34
您正在以非常高的速率生成數據,而沒有對它進行任何限制。你的鎖定是完全無效的。使用.NET BlockingCollection <>類。 – 2013-04-27 23:05:50