【发布时间】:2009-08-29 15:24:01
【问题描述】:
我正在使用 National Instruments Daqmx 用 C# 开发一个应用程序,以便在某些硬件上执行测量。
我的设置由几个检测器组成,我必须在设定的时间段内从中获取数据,同时使用这些数据更新我的 UI。
public class APD : IDevice
{
// Some members and properties go here, removed for clarity.
public event EventHandler ErrorOccurred;
public event EventHandler NewCountsAvailable;
// Constructor
public APD(
string __sBoardID,
string __sPulseGenCtr,
string __sPulseGenTimeBase,
string __sPulseGenTrigger,
string __sAPDTTLCounter,
string __sAPDInputLine)
{
// Removed for clarity.
}
private void APDReadCallback(IAsyncResult __iaresResult)
{
try
{
if (this.m_daqtskRunningTask == __iaresResult.AsyncState)
{
// Get back the values read.
UInt32[] _ui32Values = this.m_rdrCountReader.EndReadMultiSampleUInt32(__iaresResult);
// Do some processing here!
if (NewCountsAvailable != null)
{
NewCountsAvailable(this, new EventArgs());
}
// Read again only if we did not yet read all pixels.
if (this.m_dTotalCountsRead != this.m_iPixelsToRead)
{
this.m_rdrCountReader.BeginReadMultiSampleUInt32(-1, this.m_acllbckCallback, this.m_daqtskAPDCount);
}
else
{
// Removed for clarity.
}
}
}
catch (DaqException exception)
{
// Removed for clarity.
}
}
private void SetupAPDCountAndTiming(double __dBinTimeMilisec, int __iSteps)
{
// Do some things to prepare hardware.
}
public void StartAPDAcquisition(double __dBinTimeMilisec, int __iSteps)
{
this.m_bIsDone = false;
// Prepare all necessary tasks.
this.SetupAPDCountAndTiming(__dBinTimeMilisec, __iSteps);
// Removed for clarity.
// Begin reading asynchronously on the task. We always read all available counts.
this.m_rdrCountReader.BeginReadMultiSampleUInt32(-1, this.m_acllbckCallback, this.m_daqtskAPDCount);
}
public void Stop()
{
// Removed for clarity.
}
}
表示检测器的对象基本上调用 BeginXXX 操作,并带有一个包含 EndXXX 的回调 en 还会触发一个指示数据可用的事件。
我有多达 4 个这样的检测器对象作为我的 UI 表单的成员。我依次调用所有它们的 Start() 方法来开始我的测量。这有效,并且所有四个都会触发 NewCountsAvailable 事件。
由于我实现的性质,在 UI 线程上调用 BeginXXX 方法,并且 Callback 和 Event 也在此 UI 线程上。因此,我不能在我的 UI 线程中使用某种 while 循环来不断用新数据更新我的 UI,因为事件会不断触发(我试过这个)。我也不想在四个 NewCountsAvailable 事件处理程序中都使用某种 UpdateUI() 方法,因为这会使我的系统负载过多。
由于我是 C# 线程编程的新手,我现在陷入困境;
1) 处理这种情况的“正确”方法是什么? 2)我的检测器对象声音的实现吗?我应该从另一个线程调用这四个检测器对象的 Start() 方法吗? 3) 我可以使用计时器每隔几百毫秒更新一次我的 UI,而不管 4 个检测器对象在做什么吗?
我真的不知道!
【问题讨论】:
-
您使用的是什么版本的 .NET?
-
nidaq 在 UI 线程上的回调如何? (意思是:你确定吗?)
-
您需要在 GUI 中显示多少数据?我们在说视频吗?我同意 gimpf 的评论,请确定。
-
@James:基本上.NET 3.5,不需要限制.NET版本。 @ Gimf & Henk: APD.StartAPDAquisition() 在 ButtonClick 事件处理程序中的 UI 线程上调用。因此,也在 UI 线程上调用 BeginReadMultiSampleUInt32(...)。这也意味着回调将在每个定义的这个线程上。我检查了这一点,使用在 Threading 类中获取线程句柄的调用。数据量大约是 4 到 5 个数组,包含 512*512 个元素……当然没有视频流。
标签: c# concurrency user-interface multithreading