I am developing an application in C# using National Instruments Daqmx for performing measurements on certain hardware.
My setup consists of several detectors from which I have to get data during a set period of time, all the while updating my UI with this data.
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.
}
}
The object representing the detector basically calls a BeginXXX operation with a callback that holds the EndXXX en also fires an event indicating data available.
I have up to 4 of these detector objects as members of my UI form. I call the Start() method on all of them in sequence to start my measurement. This works and the NewCountsAvailable event fires for all four of them.
Due to the nature of my implementation, the BeginXXX method is called on the UI thread and the Callback and the Event are also on this UI thread. Therefore I cannot use some kind of while loop inside my UI thread to constantly update my UI with the new data because the events constantly fire (I tried this). I also do not want to use some kind of UpdateUI() method in each of the four NewCountsAvailable eventhandlers since this will load my system too much.
Since I am new to threaded programming in C# I am now stuck;
1) What is the "proper" way to handle a situation like this? 2) Is my implementation of the detector object sound? Should I call the Start() methods on these four detector objects from yet another thread? 3) Could I use a timer to update my UI every few hundred miliseconds, irrespective of what the 4 detector objects are doing?
I really have no clue!