Application.DoEvents() triggers exception!

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • james.jdunne@gmail.com

    Application.DoEvents() triggers exception!

    System.Argument Exception: Item has already been added. Key in
    dictionary: "-1" Key being added: "-1"
    at System.Collecti ons.Hashtable.I nsert(Object key, Object nvalue,
    Boolean add)
    at System.Collecti ons.Hashtable.A dd(Object key, Object value)
    at
    System.Windows. Forms.Component Manager.System. Windows.Forms.U nsafeNativeMeth ods+IMsoCompone ntManager.FRegi sterComponent(I MsoComponent
    component, MSOCRINFOSTRUCT pcrinfo, Int32& dwComponentID)
    at System.Windows. Forms.ThreadCon text.get_Compon entManager()
    at System.Windows. Forms.ThreadCon text.RunMessage LoopInner(Int32
    reason, ApplicationCont ext context)
    at System.Windows. Forms.ThreadCon text.RunMessage Loop(Int32 reason,
    ApplicationCont ext context)
    at System.Windows. Forms.Applicati on.DoEvents()

    I'm working with the Windows Media Encoder object library, needing to
    call Application.DoE vents() 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.Trans code() 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.DoE vents() in
    the while (!done) loop.

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

    namespace WMEncoderWrappe r {
    /// <summary>
    /// Summary description for WMEncoder.
    /// </summary>
    public class WMEncoder {
    private const int WMENC_CONTENT_O NE_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(W MEncoderLib.WME NC_ENCODER_STAT E state) {
    if (state == WMEncoderLib.WM ENC_ENCODER_STA TE.WMENC_ENCODE R_STOPPED)
    done = true;
    }

    /// <summary>
    /// Transcode the input audio file (MP3, WMA, etc.) to a WMA9STD file
    at 64kbps
    /// </summary>
    /// <param name="inputFile "></param>
    /// <param name="outputFil e"></param>
    public void Transcode(strin g inputFile, string outputFile) {
    WMEncoderLib.WM Encoder enc = null;
    WMEncoderLib.IW MEncSourceGroup srcGroup = null;
    WMEncoderLib.IW MEncSource src = null;
    WMEncoderLib.IW MEncProfile2 profile = null;
    WMEncoderLib.IW MEncAudienceObj audience = null;

    try {
    done = false;

    // Create encoder:
    enc = new WMEncoderLib.WM EncoderClass();
    enc.OnStateChan ge += new
    WMEncoderLib._I WMEncoderEvents _OnStateChangeE ventHandler(OnS tateChange);

    profile = new WMEncoderLib.WM EncProfile2Clas s();
    profile.Content Type = WMENC_CONTENT_O NE_AUDIO;
    profile.Profile Name = "Profile1";
    audience = profile.AddAudi ence(10000000);

    // Set the encoding codec to WMA9STD with 1-pass CBR encoding:
    int idxCodec =
    profile.GetCode cIndexFromFourC C(WMEncoderLib. WMENC_SOURCE_TY PE.WMENC_AUDIO,
    WMA9STD_FOURCC) ;
    //profile.EnumAud ioCodec(idxCode c, out codecName);
    audience.set_Au dioCodec(0, idxCodec);

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

    // Create a source group:
    srcGroup = enc.SourceGroup Collection.Add( "SG_1");
    srcGroup.set_Pr ofile(profile);

    // Set the input file:
    src =
    srcGroup.AddSou rce(WMEncoderLi b.WMENC_SOURCE_ TYPE.WMENC_AUDI O);
    src.SetInput(in putFile, String.Empty, String.Empty);

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

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

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

    // Yield to other threads.
    System.Threadin g.Thread.Sleep( 0);
    }
    enc.Stop();
    } finally {
    if (enc != null) Marshal.Release ComObject(enc);
    if (srcGroup != null) Marshal.Release ComObject(srcGr oup);
    if (src != null) Marshal.Release ComObject(src);
    if (profile != null) Marshal.Release ComObject(profi le);
    if (audience != null) Marshal.Release ComObject(audie nce);
    }
    }
    }
    }

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

  • David Browne

    #2
    Re: Application.DoE vents() triggers exception!



    <james.jdunne@g mail.comwrote in message
    news:1159800471 .957348.170890@ c28g2000cwb.goo glegroups.com.. .
    System.Argument Exception: Item has already been added. Key in
    dictionary: "-1" Key being added: "-1"
    at System.Collecti ons.Hashtable.I nsert(Object key, Object nvalue,
    Boolean add)
    at System.Collecti ons.Hashtable.A dd(Object key, Object value)
    at
    System.Windows. Forms.Component Manager.System. Windows.Forms.U nsafeNativeMeth ods+IMsoCompone ntManager.FRegi sterComponent(I MsoComponent
    component, MSOCRINFOSTRUCT pcrinfo, Int32& dwComponentID)
    at System.Windows. Forms.ThreadCon text.get_Compon entManager()
    at System.Windows. Forms.ThreadCon text.RunMessage LoopInner(Int32
    reason, ApplicationCont ext context)
    at System.Windows. Forms.ThreadCon text.RunMessage Loop(Int32 reason,
    ApplicationCont ext context)
    at System.Windows. Forms.Applicati on.DoEvents()
    >
    I'm working with the Windows Media Encoder object library, needing to
    call Application.DoE vents() 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.Trans code() 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

    Comment

    • Samuel R. Neff

      #3
      Re: Application.DoE vents() triggers exception!


      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.


      Comment

      • james.jdunne@gmail.com

        #4
        Re: Application.DoE vents() triggers exception!


        David Browne wrote:
        <james.jdunne@g mail.comwrote in message
        news:1159800471 .957348.170890@ c28g2000cwb.goo glegroups.com.. .
        System.Argument Exception: Item has already been added. Key in
        dictionary: "-1" Key being added: "-1"
        at System.Collecti ons.Hashtable.I nsert(Object key, Object nvalue,
        Boolean add)
        at System.Collecti ons.Hashtable.A dd(Object key, Object value)
        at
        System.Windows. Forms.Component Manager.System. Windows.Forms.U nsafeNativeMeth ods+IMsoCompone ntManager.FRegi sterComponent(I MsoComponent
        component, MSOCRINFOSTRUCT pcrinfo, Int32& dwComponentID)
        at System.Windows. Forms.ThreadCon text.get_Compon entManager()
        at System.Windows. Forms.ThreadCon text.RunMessage LoopInner(Int32
        reason, ApplicationCont ext context)
        at System.Windows. Forms.ThreadCon text.RunMessage Loop(Int32 reason,
        ApplicationCont ext context)
        at System.Windows. Forms.Applicati on.DoEvents()

        I'm working with the Windows Media Encoder object library, needing to
        call Application.DoE vents() 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.Trans code() 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.

        Comment

        • james.jdunne@gmail.com

          #5
          Re: Application.DoE vents() triggers exception!


          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.

          Comment

          • Samuel R. Neff

            #6
            Re: Application.DoE vents() triggers exception!


            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, james.jdunne@gm ail.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.

            Comment

            Working...