How to synchronize the container application through events |
|
Some method available inside Audio DJ Studio for .NET performs lengthy operations which, on a single-threaded environment, could block the user interface of the container application also for several seconds: just think about the time requested to perform the waveform analysis for a song longer than 5 minutes and you will perfectly understand that this operation couldn't be completed in less than one second.
In order to avoid this kind of blocks, the control performs lengthy operations inside secondary threads; the main side effect of this multithreaded approach is the fact that, when the method call returns, the requested operation could still be running in the background so requested data wouldn't be already available and any method call trying to access data would fail by returning an error code; for this reason it's very important that the container application synchronizes itself with events fired by the control.
Just to make a practical example, let's take the mentioned waveform's analysis calculation for having a better understanding of the issue: the container application requests the calculation of the sound's waveform through a call to the Waveform.AnalyzeFullSound method; when this method returns, the waveform is still being calculated in background and the container application will be notified about calculation advancement through the following events:
WaveAnalysisStart : this event is generated immediately before starting the secondary calculation thread; the container application could catch it in order to display a hidden progress bar that could be used to notify the user about the analysis advancement.
WaveAnalysisPerc : this event is generated during the calculation; the container application could catch it in order to modify the mentioned progress bar value
WaveAnalysisDone : this event is generated immediately before closing the secondary thread; the container application could catch it in order to hide back the progress bar and, eventually, to display a message to the user
After receiving the last event, the container application could request further operations on the calculated waveform, for example it could request to obtain the bitmap representation of the waveform through a call to the Waveform.BitmapViewSaveToFile method: it's very important to remember that a call to a method of a certain .NET component should be never performed from within a management function of an event generated by the same .NET component: this is usually cause of errors and dead-lock situations and it's a practice that should be always avoided; the best approach in cases like this would be using the WaveAnalysisDone event to trigger a one shot-timer and to call the Waveform.BitmapViewSaveToFile method from within the management function of the timer's event.
As a further suggestion, keep management functions of events generated by the component as fast/short as possible and never use them in order to display messages or dialog boxes which require user interaction.
How to create and use one-shot timers in C#
The procedure below allows using a single one-shot timer that could manage th situations described above:
• | At design-time, from the Visual Studio toolbox, insert a Timer object inside the form containing the Audio Sound Recorder component: inside this sample it will be named TimerSync |
• | At design-time, set the Enabled property of the timer object to False |
• | At design-time, set the Interval property of the timer object to 50 |
Supposing that we have requested the waveform analysis through a call to the Waveform.AnalyzeFullSound method, catch the WaveAnalysisDone event like this:
private void audioDjStudio1_WaveAnalysisDone(object sender, WaveAnalysisDoneEventArgs e) { // store detected peaks m_nTotalWavePeaks = e.nTotalPeaksDetected; m_fPeakDurationInMs = e.fPeakDurationInMs;
// start the one-shot timer TimerSync.Enabled = true; }
|
At this point we can modify the handler of the TimerSync timer in order to manage the bitmap creation feature:
private void TimerSync_Tick(object sender, System.EventArgs e) { // avoid unwanted recursions TimerSync.Enabled = false;
//////////////////////////////////////////////////////// // just for demonstration, add a trigger each 10 seconds
// calculate the number of triggers Int32 nTriggers = audioDjStudio1.SoundDurationGet(0) / 10000;
Int32 nPos = 0; for (Int32 i = 0; i < nTriggers; i++) { nPos += 10000; audioDjStudio1.TriggersAdd (0, i, nPos); }
// display a red vertical line for each trigger for (int i = 0; i < audioDjStudio1.TriggersGetCount(0); i++) audioDjStudio1.DisplayWaveform.BitmapViewVerticalLineAdd (0, i, audioDjStudio1.TriggersGetPos(0, i), Color.Red,enumWaveformLineModes.LINE_MODE_SOLID, 2); }
|
A sample of use of the one-shot timer in Visual C# and Visual Basic.NET can be found inside the following samples installed with the product's setup package:
- WaveformScroll