By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,056 Members | 1,320 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,056 IT Pros & Developers. It's quick & easy.

Application.DoEvents() triggers exception!

P: n/a
System.ArgumentException: Item has already been added. Key in
dictionary: "-1" Key being added: "-1"
at System.Collections.Hashtable.Insert(Object key, Object nvalue,
Boolean add)
at System.Collections.Hashtable.Add(Object key, Object value)
at
System.Windows.Forms.ComponentManager.System.Windo ws.Forms.UnsafeNativeMethods+IMsoComponentManager. FRegisterComponent(IMsoComponent
component, MSOCRINFOSTRUCT pcrinfo, Int32& dwComponentID)
at System.Windows.Forms.ThreadContext.get_ComponentMa nager()
at System.Windows.Forms.ThreadContext.RunMessageLoopI nner(Int32
reason, ApplicationContext context)
at System.Windows.Forms.ThreadContext.RunMessageLoop( Int32 reason,
ApplicationContext context)
at System.Windows.Forms.Application.DoEvents()

I'm working with the Windows Media Encoder object library, needing to
call Application.DoEvents() to process the message pump to be notified
when an asynchronous encoding job completes. Unfortunately I cannot
reproduce the problem in a small complete example because it requires
the Windows Media Encoder SDK, but I will post my code nonetheless.

What I can tell you is that I'm running a two-threaded Windows.Forms
application that invokes the WMEncoder.Transcode() call from the
non-GUI thread. Also, I'm writing out a lot of output to a ListBox,
which could have been overfilled beyond 64K items. The non-GUI thread
properly calls back to the GUI thread via the BeginInvoke() procedure.

The application is basically a batch WMA file transcoder that processes
thousands of files during one instance of the application.

The following is the complete code for my transcoder wrapper class.
The exception is generated from the call to Application.DoEvents() in
the while (!done) loop.

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace WMEncoderWrapper {
/// <summary>
/// Summary description for WMEncoder.
/// </summary>
public class WMEncoder {
private const int WMENC_CONTENT_ONE_AUDIO = 1;
private const int
WMA9STD_FOURCC = 353,
WMA9PRO_FOURCC = 354,
WMA9LSL_FOURCC = 355,
WMSPEECH_FOURCC = 10,
PCM_FOURCC = 0;

private bool done = false;

public WMEncoder() {
}

/// <summary>
/// Handles an encoder state change
/// </summary>
/// <param name="state"></param>
private void OnStateChange(WMEncoderLib.WMENC_ENCODER_STATE state) {
if (state == WMEncoderLib.WMENC_ENCODER_STATE.WMENC_ENCODER_STO PPED)
done = true;
}

/// <summary>
/// Transcode the input audio file (MP3, WMA, etc.) to a WMA9STD file
at 64kbps
/// </summary>
/// <param name="inputFile"></param>
/// <param name="outputFile"></param>
public void Transcode(string inputFile, string outputFile) {
WMEncoderLib.WMEncoder enc = null;
WMEncoderLib.IWMEncSourceGroup srcGroup = null;
WMEncoderLib.IWMEncSource src = null;
WMEncoderLib.IWMEncProfile2 profile = null;
WMEncoderLib.IWMEncAudienceObj audience = null;

try {
done = false;

// Create encoder:
enc = new WMEncoderLib.WMEncoderClass();
enc.OnStateChange += new
WMEncoderLib._IWMEncoderEvents_OnStateChangeEventH andler(OnStateChange);

profile = new WMEncoderLib.WMEncProfile2Class();
profile.ContentType = WMENC_CONTENT_ONE_AUDIO;
profile.ProfileName = "Profile1";
audience = profile.AddAudience(10000000);

// Set the encoding codec to WMA9STD with 1-pass CBR encoding:
int idxCodec =
profile.GetCodecIndexFromFourCC(WMEncoderLib.WMENC _SOURCE_TYPE.WMENC_AUDIO,
WMA9STD_FOURCC);
//profile.EnumAudioCodec(idxCodec, out codecName);
audience.set_AudioCodec(0, idxCodec);

// 2 channels, 44kHz sampling rate, 64,040bps bitrate, 16-bit
samples
audience.SetAudioConfig(0, 2, 44100, 64040, 16);

// Create a source group:
srcGroup = enc.SourceGroupCollection.Add("SG_1");
srcGroup.set_Profile(profile);

// Set the input file:
src =
srcGroup.AddSource(WMEncoderLib.WMENC_SOURCE_TYPE. WMENC_AUDIO);
src.SetInput(inputFile, String.Empty, String.Empty);

// Set the output file:
enc.File.LocalFileName = outputFile;

// Transcode:
enc.AutoStop = true;
enc.PrepareToEncode(true);
enc.Start();

// Wait until encoding stops:
while (!done) {
Application.DoEvents();

// Yield to other threads.
System.Threading.Thread.Sleep(0);
}
enc.Stop();
} finally {
if (enc != null) Marshal.ReleaseComObject(enc);
if (srcGroup != null) Marshal.ReleaseComObject(srcGroup);
if (src != null) Marshal.ReleaseComObject(src);
if (profile != null) Marshal.ReleaseComObject(profile);
if (audience != null) Marshal.ReleaseComObject(audience);
}
}
}
}

I've seen others in this newsgroup post about similar problems but with
no resolve on the issue. Can someone investigate this problem?

Oct 2 '06 #1
Share this Question
Share on Google+
5 Replies


P: n/a


<ja**********@gmail.comwrote in message
news:11**********************@c28g2000cwb.googlegr oups.com...
System.ArgumentException: Item has already been added. Key in
dictionary: "-1" Key being added: "-1"
at System.Collections.Hashtable.Insert(Object key, Object nvalue,
Boolean add)
at System.Collections.Hashtable.Add(Object key, Object value)
at
System.Windows.Forms.ComponentManager.System.Windo ws.Forms.UnsafeNativeMethods+IMsoComponentManager. FRegisterComponent(IMsoComponent
component, MSOCRINFOSTRUCT pcrinfo, Int32& dwComponentID)
at System.Windows.Forms.ThreadContext.get_ComponentMa nager()
at System.Windows.Forms.ThreadContext.RunMessageLoopI nner(Int32
reason, ApplicationContext context)
at System.Windows.Forms.ThreadContext.RunMessageLoop( Int32 reason,
ApplicationContext context)
at System.Windows.Forms.Application.DoEvents()

I'm working with the Windows Media Encoder object library, needing to
call Application.DoEvents() to process the message pump to be notified
when an asynchronous encoding job completes. Unfortunately I cannot
reproduce the problem in a small complete example because it requires
the Windows Media Encoder SDK, but I will post my code nonetheless.

What I can tell you is that I'm running a two-threaded Windows.Forms
application that invokes the WMEncoder.Transcode() call from the
non-GUI thread. . . .
If Transcode is called from a background thread, why is it calling DoEvents
at all? If you need to wait for the job to complete, the Thread.Sleep
should do it. But don't sleep(0), or that thread will constantly get
scheduled: Sleep(100) at least.

David

Oct 2 '06 #2

P: n/a

Since you get event notification when the transcoding is complete you
don't need to poll for done. Just move the local variables to
instance variables, end Transcode() after Start() and then do the
finally stuff when the done event comes in.

HTH,

Sam
------------------------------------------------------------
We're hiring! B-Line Medical is seeking Mid/Sr. .NET
Developers for exciting positions in medical product
development in MD/DC. Work with a variety of technologies
in a relaxed team environment. See ads on Dice.com.
Oct 2 '06 #3

P: n/a

David Browne wrote:
<ja**********@gmail.comwrote in message
news:11**********************@c28g2000cwb.googlegr oups.com...
System.ArgumentException: Item has already been added. Key in
dictionary: "-1" Key being added: "-1"
at System.Collections.Hashtable.Insert(Object key, Object nvalue,
Boolean add)
at System.Collections.Hashtable.Add(Object key, Object value)
at
System.Windows.Forms.ComponentManager.System.Windo ws.Forms.UnsafeNativeMethods+IMsoComponentManager. FRegisterComponent(IMsoComponent
component, MSOCRINFOSTRUCT pcrinfo, Int32& dwComponentID)
at System.Windows.Forms.ThreadContext.get_ComponentMa nager()
at System.Windows.Forms.ThreadContext.RunMessageLoopI nner(Int32
reason, ApplicationContext context)
at System.Windows.Forms.ThreadContext.RunMessageLoop( Int32 reason,
ApplicationContext context)
at System.Windows.Forms.Application.DoEvents()

I'm working with the Windows Media Encoder object library, needing to
call Application.DoEvents() to process the message pump to be notified
when an asynchronous encoding job completes. Unfortunately I cannot
reproduce the problem in a small complete example because it requires
the Windows Media Encoder SDK, but I will post my code nonetheless.

What I can tell you is that I'm running a two-threaded Windows.Forms
application that invokes the WMEncoder.Transcode() call from the
non-GUI thread. . . .

If Transcode is called from a background thread, why is it calling DoEvents
at all? If you need to wait for the job to complete, the Thread.Sleep
should do it. But don't sleep(0), or that thread will constantly get
scheduled: Sleep(100) at least.

David
The Windows Media Encoder library's callback mechanism does not work
unless the Windows message pump is running. I've tried without the
DoEvents call and it does not ever fire the event, even after I know
the transcoding is done (watching the filesystem).

Besides, the real problem here is why DoEvents is throwing an exception
about Hashtable.

Oct 4 '06 #4

P: n/a

Samuel R. Neff wrote:
Since you get event notification when the transcoding is complete you
don't need to poll for done. Just move the local variables to
instance variables, end Transcode() after Start() and then do the
finally stuff when the done event comes in.

HTH,

Sam
------------------------------------------------------------
We're hiring! B-Line Medical is seeking Mid/Sr. .NET
Developers for exciting positions in medical product
development in MD/DC. Work with a variety of technologies
in a relaxed team environment. See ads on Dice.com.
I would do that if I wanted my Transcode() function to be asynchronous,
but I don't want that. I want it as part of a batch process and I want
the batch to run sequentially so I get meaningful log output.

Oct 4 '06 #5

P: n/a

If you don't want Transcode() to be async then don't use a separate
thread. Run the Transcode on the main message thread (although this
is very unusual in normal WinForm programming methodology--background
processes normally don't run on the UI thread and normally don't
require the message pump).

Sam
------------------------------------------------------------
We're hiring! B-Line Medical is seeking Mid/Sr. .NET
Developers for exciting positions in medical product
development in MD/DC. Work with a variety of technologies
in a relaxed team environment. See ads on Dice.com.

On 4 Oct 2006 11:36:38 -0700, ja**********@gmail.com wrote:
>
Samuel R. Neff wrote:
>Since you get event notification when the transcoding is complete you
don't need to poll for done. Just move the local variables to
instance variables, end Transcode() after Start() and then do the
finally stuff when the done event comes in.

HTH,

Sam
------------------------------------------------------------
We're hiring! B-Line Medical is seeking Mid/Sr. .NET
Developers for exciting positions in medical product
development in MD/DC. Work with a variety of technologies
in a relaxed team environment. See ads on Dice.com.

I would do that if I wanted my Transcode() function to be asynchronous,
but I don't want that. I want it as part of a batch process and I want
the batch to run sequentially so I get meaningful log output.
Oct 6 '06 #6

This discussion thread is closed

Replies have been disabled for this discussion.