我试图实现一个典型的线程应用程序,其中一个线程询问设备是否有数据可用,将数据复制到其自己的内存并将数据发送到数据可用的主线程。主线程将数据复制到其自己的内存并将其显示在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