Система B * * * dy captcha решила, что было бы неплохо потерять мой ответ. Я потратил полчаса, набирая текст без предупреждения или шанса исправить ... так что мы снова идем:
public class APD : IDevice
{
// Some members and properties go here, removed for clarity.
public event EventHandler ErrorOccurred;
public event EventHandler NewCountsAvailable;
public UInt32[] BufferedCounts
{
// Get for the _ui32Values returned by the EndReadMultiSampleUInt32()
// after they were appended to a list. BufferdCounts therefore supplies
// all values read during the experiment.
}
public bool IsDone
{
// This gets set when a preset number of counts is read by the hardware or when
// Stop() is called.
}
// Constructor
public APD( some parameters )
{
// 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.
}
}
Обратите внимание, я добавил некоторые вещи, которые я по ошибке пропустил в оригинальном сообщении.
Теперь в моей форме есть такой код;
public partial class Form1 : Form
{
private APD m_APD1;
private APD m_APD2;
private APD m_APD3;
private APD m_APD4;
private DataDocument m_Document;
public Form1()
{
InitializeComponent();
}
private void Button1_Click()
{
this.m_APD1 = new APD( ... ); // times four for all APD's
this.m_APD1.NewCountsAvailable += new EventHandler(m_APD1_NewCountsAvailable); // times 4 again...
this.m_APD1.StartAPDAcquisition( ... );
this.m_APD2.StartAPDAcquisition( ... );
this.m_APD3.StartAPDAcquisition( ... );
this.m_APD4.StartAPDAcquisition( ... );
while (!this.m_APD1.IsDone) // Actually I have to check all 4
{
Thread.Sleep(200);
UpdateUI();
}
// Some more code after the measurement is done.
}
private void m_APD1_NewCountsAvailable(object sender, EventArgs e)
{
this.m_document.Append(this.m_APD1.BufferedCounts);
}
private void UpdateUI()
{
// use the data contained in this.m_Document to fill the UI.
}
}
тьфу, надеюсь, я не забуду что-нибудь еще во второй раз (это научит меня не копировать это до того, как я нажму на Post).
То, что я вижу, запустив этот код, таково:
1) Объект APD работает как рекламируется, он измеряет.
2) Возникают события NewCountsAvailable и выполняются их обработчики
3) APD.StartAPDAcquisition () вызывается в потоке пользовательского интерфейса. Таким образом, BeginXXX также вызывается в этом потоке. Следовательно, по замыслу обратный вызов также находится в этом потоке, и, очевидно, обработчики событий NewCountsAvailable выполняются в потоке пользовательского интерфейса. Единственное, чего нет в потоке пользовательского интерфейса, - это ожидание аппаратного обеспечения для возврата значений в пару вызовов BeginXXX EndXXX.
4) Поскольку события NewCountsAvailable запускаются довольно часто, цикл while, который я намеревался использовать для обновления пользовательского интерфейса, не запускается. Обычно он запускается один раз в начале, а затем каким-то образом прерывается обработчиками событий, которые необходимо обработать. Я не до конца понимаю это, но это не работает ...
Я думал решить эту проблему, избавившись от цикла while и поместив Forms.Timer в форму, где UpdateUI () будет вызываться из обработчика событий Tick. Однако я не знаю, будет ли это считаться «лучшей практикой». Я также не знаю, приведут ли все эти обработчики событий в конечном итоге к потоку пользовательского интерфейса для сканирования, возможно, мне придется добавить еще несколько таких объектов APD в будущем. Также UpdateUI () может содержать более тяжелый код для вычисления изображения на основе значений в m_Document. Таким образом, тик-обработчик событий также может быть истощением ресурсов в подходе таймера. В случае, если я использую это решение, мне также понадобится событие «Готово» в моем классе APD, чтобы уведомить о завершении каждого APD.
Должен ли я, возможно, не работать с событиями для уведомления о наличии новых счетчиков, а вместо этого работать с каким-либо чтением "APD.BufferedCounts" по требованию и помещать все это в еще один поток? Я действительно понятия не имею ...
Мне в основном нужно чистое, легкое решение, которое хорошо масштабируется, если я добавлю еще больше APD:)