Re: Best way to design multithreading application



Dave wrote:
[...]
That's pretty much what I'm shooting for, but there will be cases it
runs on one core, but will still need to acquire data while UI is
updating. I guess threads will solve both situations.

Yes. Threading can solve architectural issues, performance issues, or both.

Unfortunately, there is no async. The only interface we have to the
device is a single call to an OEM DLL, which takes a single
acquisition (30ms) and returns the data as a double[2048]. Thus, any
async methods we have to develop ourselves. Right now there is a loop
for acquiring, set up like this:
while(DateTime.now < NextAcqEndDate)
addToMainArray(OEM_DLL.acquireData());

So, for 1 second acquisitions, this will keep adding the result to an
array, and at the end of this loop it averages the array over number
of counts (the number of times acquireData() is called), and returns
it.

What does it do with the average? What else is done with the array? Is that what you write to the file?

As far as the average goes, it seems to me that it would be better to calculate the sum for the average as you get the data. The addition is a trivial operation, and it will reduce the number of times you enumerate the array by one.

Of course, if _all_ you're doing is calculating the average then obviously you don't even need the array. So I'm taking as granted that you do something else with that data besides calculating the average.

acquireData() takes 30ms, and that's the portion we would like to
keep going. As you can see, in a linear algorithm, this thing runs for
1 second, stops acquiring, and finishes all the other updates. Due to
the nature of chemical detection, we'd obviously like to keep this
going as long as possible, even if it has to call acquireData() in
discrete chunks, so long as the chunks are not 1s gaps like now.

I have never used the BeginInvoke and BeginWrite methods, so that
alone may offer a good start to this problem.

Based on your description, it sounds as though at the least you should be able to use BeginInvoke() rather than having a separate thread for dealing with the UI. BeginInvoke() would pass whatever data is useful for updating the UI, and then the actual work would wind up occuring on the UI thread itself.

Whether BeginWrite would be helpful or not, I'm not entirely sure. I just noticed in the docs that it says that for writes shorter than 64KB, using BeginWrite could actually reduce performance.

I suspect that this applies only to the i/o performance itself and so assuming you're not pushing the limits of the disk bandwidth (and if you're only generating 8K of data per second, you shouldn't be :) ) the architectural gain should be well worth any minimal performance reduction (noting that the performance reduction wouldn't affect the data acquisition, just how fast the data gets to the disk).

If you are looking to support extremely high data rates though, that issue might be a consideration. If so, you'd either want to batch up your data so that you're writing 64KB or more at a time, or use a separate thread to handle the file i/o (as in the original conception in this discussion thread). It doesn't sound like this would be an issue, but I mention it just in case.

Pete
.