Copyright © 2005-2019 MultiMedia Soft

How to synchronize the container application through events

Previous pageReturn to chapter overviewNext page

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