473,757 Members | 7,200 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Application.DoE vents() and COM

I understand the use of Application.DoE vents() to process all outstanding
messages on the message queue in a winforms application if you have long
running process on the UI thread. But can anyone explain to me why I need to
call DoEvents when I am using a COM component that calls back to into the
..Net application? - If I don't call DoEvents after receiving a callback then
sometimes no more messages are pumped, it appears that the message pump is
suspended until the call is made.

I suspect that when a callback occurs from COM into the .Net process that it
will not be guaranteed to be executed on the UI thread is this true?
( Note: I do know about updating the UI thread from a worker thread so
people pleased don't try and tell me about the 'Invoke' method on the
Control class)

Cheers

Ollie Riches
Nov 17 '05 #1
6 4297
DoEvents() should never be called nor in a COM interop scenario and not on
the UI thread. All you have to do is make sure you don't block the message
pumping/dispatching by calling functions or running code that take a long
time before yielding (~300msec. might be too long for a decent user
experience). The same thing goes for a COM callback that runs on the UI
thread, messages aren't dispatched as long as the callback code runs.
Now it's hard to tell what happens in your code without some more context
(apartment requirements of COM object) and seeing any code; What's not clear
is where you call DoEvents() on a UI thread that is not pumping, so it looks
like your code blocks the message while running in a tight loop and you call
DoEvents in the loop.

Willy.


"Ollie Riches" <ol**********@p honeanalyser.ne t> wrote in message
news:en******** ******@tk2msftn gp13.phx.gbl...
I understand the use of Application.DoE vents() to process all outstanding
messages on the message queue in a winforms application if you have long
running process on the UI thread. But can anyone explain to me why I need
to call DoEvents when I am using a COM component that calls back to into
the .Net application? - If I don't call DoEvents after receiving a callback
then sometimes no more messages are pumped, it appears that the message
pump is suspended until the call is made.

I suspect that when a callback occurs from COM into the .Net process that
it will not be guaranteed to be executed on the UI thread is this true?
( Note: I do know about updating the UI thread from a worker thread so
people pleased don't try and tell me about the 'Invoke' method on the
Control class)

Cheers

Ollie Riches

Nov 17 '05 #2
Thanks for the reply Willy,

If you should never call DoEvents() then I have to ask why was it included? I believe it is similar to including GC.Collect in that it is exposed to the public for use in extreme circumstances.

I can understand that while a message is being processed that no other message can be processed hence the name synchronous message processing.

I can give an example taken straight from the support site of the product I am using, you can probably guess the product involved in the code. I am well aware that any code published on any site is not always the correct way to solve a problem. The code in question uses the primary interop assembly that was generated by the vendor.

If you are using (primary) COM interop library are you required to initialise COM ? - as far as I am aware you do not have too.

Here is the complete winforms example, check out the method 'Display_Instru ment_Informatio n'
Cheers

Ollie Riches

using System;

using System.Drawing;

using System.Collecti ons;

using System.Componen tModel;

using System.Windows. Forms;

using System.Data;

namespace PriceUpdate

{

/// <summary>

/// Summary description for Form1.

/// </summary>

public class Form1 : System.Windows. Forms.Form

{

private System.Windows. Forms.Label label1;

private System.Windows. Forms.Label label2;

private System.Windows. Forms.Label label3;

private System.Windows. Forms.Label label4;

private System.Windows. Forms.Label label5;

private System.Windows. Forms.Label lblContract;

private System.Windows. Forms.Label lblProdTape;

private System.Windows. Forms.Label lblProduct;

private System.Windows. Forms.Label lblExchange;

private System.Windows. Forms.Label label6;

private System.Windows. Forms.Label label7;

private System.Windows. Forms.Label label8;

private System.Windows. Forms.Label label9;

private System.Windows. Forms.Label label14;

private System.Windows. Forms.Label label15;

private System.Windows. Forms.Label lblAskQty;

private System.Windows. Forms.Label lblAskPrice;

private System.Windows. Forms.Label lblBidQty;

private System.Windows. Forms.Label lblBidPrice;

private System.Windows. Forms.Label lblLastQty;

private System.Windows. Forms.Label lblLastPrice;

/// <summary>

/// Required designer variable.

/// </summary>

private System.Componen tModel.Containe r components = null;

// using XTAPI objects

// this sample will need the drag and drop handler class,

// the Instrument object to temporary hold the selected instrument,

// and the instrument notification class for price updates

private XTAPI.TTDropHan dlerClass m_DropHandler = null;

private XTAPI.TTInstrOb j m_LiveInstr = null;

private XTAPI.TTInstrNo tifyClass m_InstrNotify = null;

public Form1()

{

//

// Required for Windows Form Designer support

//

InitializeCompo nent();

}

/// <summary>

/// Clean up any resources being used.

/// </summary>

protected override void Dispose( bool disposing )

{

if( disposing )

{

if (components != null)

{

components.Disp ose();

}

}

base.Dispose( disposing );

}

#region Windows Form Designer generated code

/// <summary>

/// Required method for Designer support - do not modify

/// the contents of this method with the code editor.

/// </summary>

private void InitializeCompo nent()

{

this.label1 = new System.Windows. Forms.Label();

this.label2 = new System.Windows. Forms.Label();

this.label3 = new System.Windows. Forms.Label();

this.label4 = new System.Windows. Forms.Label();

this.label5 = new System.Windows. Forms.Label();

this.lblContrac t = new System.Windows. Forms.Label();

this.lblProdTap e = new System.Windows. Forms.Label();

this.lblProduct = new System.Windows. Forms.Label();

this.lblExchang e = new System.Windows. Forms.Label();

this.label6 = new System.Windows. Forms.Label();

this.label7 = new System.Windows. Forms.Label();

this.label8 = new System.Windows. Forms.Label();

this.label9 = new System.Windows. Forms.Label();

this.lblAskQty = new System.Windows. Forms.Label();

this.lblAskPric e = new System.Windows. Forms.Label();

this.lblBidQty = new System.Windows. Forms.Label();

this.lblBidPric e = new System.Windows. Forms.Label();

this.label14 = new System.Windows. Forms.Label();

this.label15 = new System.Windows. Forms.Label();

this.lblLastQty = new System.Windows. Forms.Label();

this.lblLastPri ce = new System.Windows. Forms.Label();

this.SuspendLay out();

//

// label1

//

this.label1.Loc ation = new System.Drawing. Point(16, 123);

this.label1.Nam e = "label1";

this.label1.Siz e = new System.Drawing. Size(96, 16);

this.label1.Tab Index = 17;

this.label1.Tex t = "CONTRACT:" ;

//

// label2

//

this.label2.Loc ation = new System.Drawing. Point(16, 88);

this.label2.Nam e = "label2";

this.label2.Siz e = new System.Drawing. Size(96, 16);

this.label2.Tab Index = 16;

this.label2.Tex t = "PRODUCT TYPE:";

//

// label3

//

this.label3.Loc ation = new System.Drawing. Point(16, 56);

this.label3.Nam e = "label3";

this.label3.Siz e = new System.Drawing. Size(96, 16);

this.label3.Tab Index = 15;

this.label3.Tex t = "PRODUCT:";

//

// label4

//

this.label4.Loc ation = new System.Drawing. Point(16, 19);

this.label4.Nam e = "label4";

this.label4.Siz e = new System.Drawing. Size(96, 16);

this.label4.Tab Index = 14;

this.label4.Tex t = "EXCHANGE:" ;

//

// label5

//

this.label5.Loc ation = new System.Drawing. Point(144, 256);

this.label5.Nam e = "label5";

this.label5.Siz e = new System.Drawing. Size(232, 56);

this.label5.Tab Index = 13;

this.label5.Tex t = "Drag an instrument from X_Trader Market Grid and drop it anywhere on this form.";

//

// lblContract

//

this.lblContrac t.BorderStyle = System.Windows. Forms.BorderSty le.Fixed3D;

this.lblContrac t.Location = new System.Drawing. Point(128, 120);

this.lblContrac t.Name = "lblContrac t";

this.lblContrac t.TabIndex = 12;

//

// lblProdTape

//

this.lblProdTap e.BorderStyle = System.Windows. Forms.BorderSty le.Fixed3D;

this.lblProdTap e.Location = new System.Drawing. Point(128, 88);

this.lblProdTap e.Name = "lblProdTap e";

this.lblProdTap e.TabIndex = 18;

//

// lblProduct

//

this.lblProduct .BorderStyle = System.Windows. Forms.BorderSty le.Fixed3D;

this.lblProduct .Location = new System.Drawing. Point(128, 56);

this.lblProduct .Name = "lblProduct ";

this.lblProduct .TabIndex = 19;

//

// lblExchange

//

this.lblExchang e.BorderStyle = System.Windows. Forms.BorderSty le.Fixed3D;

this.lblExchang e.Location = new System.Drawing. Point(128, 16);

this.lblExchang e.Name = "lblExchang e";

this.lblExchang e.TabIndex = 20;

//

// label6

//

this.label6.Loc ation = new System.Drawing. Point(264, 120);

this.label6.Nam e = "label6";

this.label6.Siz e = new System.Drawing. Size(96, 16);

this.label6.Tab Index = 25;

this.label6.Tex t = "ASK QTY:";

//

// label7

//

this.label7.Loc ation = new System.Drawing. Point(264, 88);

this.label7.Nam e = "label7";

this.label7.Siz e = new System.Drawing. Size(96, 16);

this.label7.Tab Index = 24;

this.label7.Tex t = "ASK PRICE:";

//

// label8

//

this.label8.Loc ation = new System.Drawing. Point(264, 56);

this.label8.Nam e = "label8";

this.label8.Siz e = new System.Drawing. Size(96, 16);

this.label8.Tab Index = 23;

this.label8.Tex t = "BID QTY:";

//

// label9

//

this.label9.Loc ation = new System.Drawing. Point(264, 19);

this.label9.Nam e = "label9";

this.label9.Siz e = new System.Drawing. Size(96, 16);

this.label9.Tab Index = 22;

this.label9.Tex t = "BID PRICE:";

//

// lblAskQty

//

this.lblAskQty. BorderStyle = System.Windows. Forms.BorderSty le.Fixed3D;

this.lblAskQty. Location = new System.Drawing. Point(376, 120);

this.lblAskQty. Name = "lblAskQty" ;

this.lblAskQty. TabIndex = 21;

//

// lblAskPrice

//

this.lblAskPric e.BorderStyle = System.Windows. Forms.BorderSty le.Fixed3D;

this.lblAskPric e.Location = new System.Drawing. Point(376, 88);

this.lblAskPric e.Name = "lblAskPric e";

this.lblAskPric e.TabIndex = 26;

//

// lblBidQty

//

this.lblBidQty. BorderStyle = System.Windows. Forms.BorderSty le.Fixed3D;

this.lblBidQty. Location = new System.Drawing. Point(376, 56);

this.lblBidQty. Name = "lblBidQty" ;

this.lblBidQty. TabIndex = 27;

//

// lblBidPrice

//

this.lblBidPric e.BorderStyle = System.Windows. Forms.BorderSty le.Fixed3D;

this.lblBidPric e.Location = new System.Drawing. Point(376, 16);

this.lblBidPric e.Name = "lblBidPric e";

this.lblBidPric e.TabIndex = 28;

//

// label14

//

this.label14.Lo cation = new System.Drawing. Point(264, 184);

this.label14.Na me = "label14";

this.label14.Si ze = new System.Drawing. Size(96, 16);

this.label14.Ta bIndex = 31;

this.label14.Te xt = "LAST QTY:";

//

// label15

//

this.label15.Lo cation = new System.Drawing. Point(264, 152);

this.label15.Na me = "label15";

this.label15.Si ze = new System.Drawing. Size(96, 16);

this.label15.Ta bIndex = 30;

this.label15.Te xt = "LAST PRICE:";

//

// lblLastQty

//

this.lblLastQty .BorderStyle = System.Windows. Forms.BorderSty le.Fixed3D;

this.lblLastQty .Location = new System.Drawing. Point(376, 184);

this.lblLastQty .Name = "lblLastQty ";

this.lblLastQty .TabIndex = 29;

//

// lblLastPrice

//

this.lblLastPri ce.BorderStyle = System.Windows. Forms.BorderSty le.Fixed3D;

this.lblLastPri ce.Location = new System.Drawing. Point(376, 152);

this.lblLastPri ce.Name = "lblLastPri ce";

this.lblLastPri ce.TabIndex = 32;

//

// Form1

//

this.AutoScaleB aseSize = new System.Drawing. Size(5, 13);

this.ClientSize = new System.Drawing. Size(496, 341);

this.Controls.A dd(this.label14 );

this.Controls.A dd(this.label15 );

this.Controls.A dd(this.lblLast Qty);

this.Controls.A dd(this.lblLast Price);

this.Controls.A dd(this.label6) ;

this.Controls.A dd(this.label7) ;

this.Controls.A dd(this.label8) ;

this.Controls.A dd(this.label9) ;

this.Controls.A dd(this.lblAskQ ty);

this.Controls.A dd(this.lblAskP rice);

this.Controls.A dd(this.lblBidQ ty);

this.Controls.A dd(this.lblBidP rice);

this.Controls.A dd(this.label1) ;

this.Controls.A dd(this.label2) ;

this.Controls.A dd(this.label3) ;

this.Controls.A dd(this.label4) ;

this.Controls.A dd(this.label5) ;

this.Controls.A dd(this.lblCont ract);

this.Controls.A dd(this.lblProd Tape);

this.Controls.A dd(this.lblProd uct);

this.Controls.A dd(this.lblExch ange);

this.Name = "Form1";

this.Text = " Price Update From";

this.Load += new System.EventHan dler(this.Form1 _Load);

this.ResumeLayo ut(false);

}

#endregion

/// <summary>

/// The main entry point for the application.

/// </summary>

///

[STAThread]

static void Main()

{

Application.Run (new Form1());

}

private void Form1_Load(obje ct sender, System.EventArg s e)

{

// initilize XTAPI needed classes and/or objects

// Instantiate the drag and drop handler class

m_DropHandler = new XTAPI.TTDropHan dlerClass();

// register the active window to enable drag and drop

m_DropHandler.R egisterDropWind ow((int) this.Handle);

// associate drop and drag events with the handler

m_DropHandler.O nNotifyDrop += new XTAPI._ITTDropH andlerEvents_On NotifyDropEvent Handler(this.m_ DropHandler_OnN otifyDrop);
// instantiate the instrument notification class

m_InstrNotify = new XTAPI.TTInstrNo tifyClass();

// associate instrument notification events with the instrument notification class

// setup the instrument notification call back function

m_InstrNotify.O nNotifyFound += new XTAPI._ITTInstr NotifyEvents_On NotifyFoundEven tHandler(this.m _InstrNotify_On NotifyFound);

// setup the instrument update call back function

m_InstrNotify.O nNotifyUpdate += new XTAPI._ITTInstr NotifyEvents_On NotifyUpdateEve ntHandler(this. m_InstrNotify_O nNotifyUpdate);

}

// XTAPI specific used functions

private void m_DropHandler_O nNotifyDrop()

{ // drag and drop call back function

try

{

// get live instrument from the call back - Index starts at 1

// cast the call back instrument as an instrument object

m_LiveInstr = (XTAPI.TTInstrO bj) m_DropHandler[1]; // 1 for a single instrument

// **** 88888888888888 *************

// must attach instrument to the notification object

m_InstrNotify.A ttachInstrument (m_LiveInstr);

// **** 88888888888888 *************
// open / access selected instrument

m_LiveInstr.Ope n(0); // turn off depth
// clear drop handler list

m_DropHandler.R eset();

}

catch (Exception e)

{

MessageBox.Show (e.Message,"Exc eption");

}

}

private void m_InstrNotify_O nNotifyFound(XT API.TTInstrNoti fy pNotify, XTAPI.TTInstrOb j pInstr)

{

// retrieve and display instrument information

Display_Instrum ent_Information (pInstr);

// retrieve and display pricing information

Get_Live_Data(p Instr);

// turn on price updates

m_InstrNotify.E nablePriceUpdat es = 1; // 1 for true

}

private void m_InstrNotify_O nNotifyUpdate(X TAPI.TTInstrNot ify pNotify, XTAPI.TTInstrOb j pInstr)

{

// retrieve live instrument prices

Get_Live_Data(p Instr);

}

private void Display_Instrum ent_Information (XTAPI.TTInstrO bj pInstr)

{

// display instrument fields onto labels

this.lblExchang e.Text = pInstr.Exchange ;

this.lblProduct .Text = pInstr.Product;

this.lblProdTap e.Text = pInstr.ProdType ;

this.lblContrac t.Text = pInstr.Contract ;

Application.DoE vents(); // force update in case it does not

}

private void Get_Live_Data(X TAPI.TTInstrObj pInstr)

{

// display instrument pricing information onto labels

this.lblBidQty. Text = (string) pInstr.get_Get( "BidQty$");

this.lblBidPric e.Text = (string) pInstr.get_Get( "Bid$");

this.lblAskPric e.Text = (string) pInstr.get_Get( "Ask$");

this.lblAskQty. Text= (string) pInstr.get_Get( "AskQty$");

this.lblLastPri ce.Text = (string) pInstr.get_Get( "Last$");

this.lblLastQty .Text = (string) pInstr.get_Get( "LastQty$") ;

Application.DoE vents(); // force update in case it does not

}

}

}
"Willy Denoyette [MVP]" <wi************ *@telenet.be> wrote in message news:eg******** ******@TK2MSFTN GP10.phx.gbl...
DoEvents() should never be called nor in a COM interop scenario and not on
the UI thread. All you have to do is make sure you don't block the message
pumping/dispatching by calling functions or running code that take a long
time before yielding (~300msec. might be too long for a decent user
experience). The same thing goes for a COM callback that runs on the UI
thread, messages aren't dispatched as long as the callback code runs.
Now it's hard to tell what happens in your code without some more context
(apartment requirements of COM object) and seeing any code; What's not clear
is where you call DoEvents() on a UI thread that is not pumping, so it looks
like your code blocks the message while running in a tight loop and you call
DoEvents in the loop.

Willy.




"Ollie Riches" <ol**********@p honeanalyser.ne t> wrote in message
news:en******** ******@tk2msftn gp13.phx.gbl...
I understand the use of Application.DoE vents() to process all outstanding
messages on the message queue in a winforms application if you have long
running process on the UI thread. But can anyone explain to me why I need
to call DoEvents when I am using a COM component that calls back to into
the .Net application? - If I don't call DoEvents after receiving a callback
then sometimes no more messages are pumped, it appears that the message
pump is suspended until the call is made.

I suspect that when a callback occurs from COM into the .Net process that
it will not be guaranteed to be executed on the UI thread is this true?
( Note: I do know about updating the UI thread from a worker thread so
people pleased don't try and tell me about the 'Invoke' method on the
Control class)

Cheers

Ollie Riches


Nov 17 '05 #3
Well I really don't know why DoEvents included, but it's heritage is VB so I guess we have to look that way. Anyway there is no need ever to call DoEvents because there is a better solution and because it's not re-entrant safe.
Now as for this code, I can hardly be sure for 100% what's going on without any more info on the COM library itself (would like to know it's threadingmodel) .
What I see is that the UI is only meant to display data, there are no input controls (buttons etc...) only output controls (labels), and the callbacks are only used to update the labels at regular intervals. There are no calls made to the COM object from the UI, that means if the COM object doesn't return after the callback, that is when it blocks (in a sleep call fi) without pumping the message queue, you are screwed, and you have to resort to hacks like DoEvents() to update the UI (redraw) before you return from the eventhandler. Again without seeing the source code of the COM objects it's hard to be sure for 100% , but I wouldn't be surprised it's like that.
All you have to do to get rid of the DoEvents hack, is create a separate thread initialized for STA, create an instance of the COM object and update the UI using Control.BeginIn voke.

Willy.


"Ollie Riches" <ol**********@p honeanalyser.ne t> wrote in message news:us******** ******@tk2msftn gp13.phx.gbl...
Thanks for the reply Willy,

If you should never call DoEvents() then I have to ask why was it included? I believe it is similar to including GC.Collect in that it is exposed to the public for use in extreme circumstances.

I can understand that while a message is being processed that no other message can be processed hence the name synchronous message processing.

I can give an example taken straight from the support site of the product I am using, you can probably guess the product involved in the code. I am well aware that any code published on any site is not always the correct way to solve a problem. The code in question uses the primary interop assembly that was generated by the vendor.

If you are using (primary) COM interop library are you required to initialise COM ? - as far as I am aware you do not have too.

Here is the complete winforms example, check out the method 'Display_Instru ment_Informatio n'
Cheers

Ollie Riches

"Willy Denoyette [MVP]" <wi************ *@telenet.be> wrote in message news:eg******** ******@TK2MSFTN GP10.phx.gbl...
DoEvents() should never be called nor in a COM interop scenario and not on
the UI thread. All you have to do is make sure you don't block the message
pumping/dispatching by calling functions or running code that take a long
time before yielding (~300msec. might be too long for a decent user
experience). The same thing goes for a COM callback that runs on the UI
thread, messages aren't dispatched as long as the callback code runs.
Now it's hard to tell what happens in your code without some more context
(apartment requirements of COM object) and seeing any code; What's not clear
is where you call DoEvents() on a UI thread that is not pumping, so it looks
like your code blocks the message while running in a tight loop and you call
DoEvents in the loop.

Willy.




"Ollie Riches" <ol**********@p honeanalyser.ne t> wrote in message
news:en******** ******@tk2msftn gp13.phx.gbl...
I understand the use of Application.DoE vents() to process all outstanding
messages on the message queue in a winforms application if you have long
running process on the UI thread. But can anyone explain to me why I need
to call DoEvents when I am using a COM component that calls back to into
the .Net application? - If I don't call DoEvents after receiving a callback
then sometimes no more messages are pumped, it appears that the message
pump is suspended until the call is made.

I suspect that when a callback occurs from COM into the .Net process that
it will not be guaranteed to be executed on the UI thread is this true?
( Note: I do know about updating the UI thread from a worker thread so
people pleased don't try and tell me about the 'Invoke' method on the
Control class)

Cheers

Ollie Riches


Nov 17 '05 #4
Thanks for the info Willy, I realised the solution after posting the reply - its always good to talk out a problem...

Cheers

Ollie Riches
"Willy Denoyette [MVP]" <wi************ *@telenet.be> wrote in message news:O9******** ******@TK2MSFTN GP12.phx.gbl...
Well I really don't know why DoEvents included, but it's heritage is VB so I guess we have to look that way. Anyway there is no need ever to call DoEvents because there is a better solution and because it's not re-entrant safe.
Now as for this code, I can hardly be sure for 100% what's going on without any more info on the COM library itself (would like to know it's threadingmodel) .
What I see is that the UI is only meant to display data, there are no input controls (buttons etc...) only output controls (labels), and the callbacks are only used to update the labels at regular intervals. There are no calls made to the COM object from the UI, that means if the COM object doesn't return after the callback, that is when it blocks (in a sleep call fi) without pumping the message queue, you are screwed, and you have to resort to hacks like DoEvents() to update the UI (redraw) before you return from the eventhandler. Again without seeing the source code of the COM objects it's hard to be sure for 100% , but I wouldn't be surprised it's like that.
All you have to do to get rid of the DoEvents hack, is create a separate thread initialized for STA, create an instance of the COM object and update the UI using Control.BeginIn voke.

Willy.


"Ollie Riches" <ol**********@p honeanalyser.ne t> wrote in message news:us******** ******@tk2msftn gp13.phx.gbl...
Thanks for the reply Willy,

If you should never call DoEvents() then I have to ask why was it included? I believe it is similar to including GC.Collect in that it is exposed to the public for use in extreme circumstances.

I can understand that while a message is being processed that no other message can be processed hence the name synchronous message processing.

I can give an example taken straight from the support site of the product I am using, you can probably guess the product involved in the code. I am well aware that any code published on any site is not always the correct way to solve a problem. The code in question uses the primary interop assembly that was generated by the vendor.

If you are using (primary) COM interop library are you required to initialise COM ? - as far as I am aware you do not have too.

Here is the complete winforms example, check out the method 'Display_Instru ment_Informatio n'
Cheers

Ollie Riches

"Willy Denoyette [MVP]" <wi************ *@telenet.be> wrote in message news:eg******** ******@TK2MSFTN GP10.phx.gbl...
DoEvents() should never be called nor in a COM interop scenario and not on
the UI thread. All you have to do is make sure you don't block the message
pumping/dispatching by calling functions or running code that take a long
time before yielding (~300msec. might be too long for a decent user
experience). The same thing goes for a COM callback that runs on the UI
thread, messages aren't dispatched as long as the callback code runs.
Now it's hard to tell what happens in your code without some more context
(apartment requirements of COM object) and seeing any code; What's not clear
is where you call DoEvents() on a UI thread that is not pumping, so it looks
like your code blocks the message while running in a tight loop and you call
DoEvents in the loop.

Willy.




"Ollie Riches" <ol**********@p honeanalyser.ne t> wrote in message
news:en******** ******@tk2msftn gp13.phx.gbl...
I understand the use of Application.DoE vents() to process all outstanding
messages on the message queue in a winforms application if you have long
running process on the UI thread. But can anyone explain to me why I need
to call DoEvents when I am using a COM component that calls back to into
the .Net application? - If I don't call DoEvents after receiving a callback
then sometimes no more messages are pumped, it appears that the message
pump is suspended until the call is made.

I suspect that when a callback occurs from COM into the .Net process that
it will not be guaranteed to be executed on the UI thread is this true?
( Note: I do know about updating the UI thread from a worker thread so
people pleased don't try and tell me about the 'Invoke' method on the
Control class)

Cheers

Ollie Riches


Nov 17 '05 #5
Turns out the problem was related to the threading model, it should have been MTA not STA, with the wrong threading apartment the code required the use of Application.DoE vents().

So the next question is - why would having the wrong thread apartment for an unmanaged COM component cause the message pump to not work correctly and require the use of Application.DoE vents()?
Cheers

Ollie Riches

"Ollie Riches" <ol**********@p honeanalyser.ne t> wrote in message news:un******** ******@TK2MSFTN GP10.phx.gbl...
Thanks for the info Willy, I realised the solution after posting the reply - its always good to talk out a problem...

Cheers

Ollie Riches
"Willy Denoyette [MVP]" <wi************ *@telenet.be> wrote in message news:O9******** ******@TK2MSFTN GP12.phx.gbl...
Well I really don't know why DoEvents included, but it's heritage is VB so I guess we have to look that way. Anyway there is no need ever to call DoEvents because there is a better solution and because it's not re-entrant safe.
Now as for this code, I can hardly be sure for 100% what's going on without any more info on the COM library itself (would like to know it's threadingmodel) .
What I see is that the UI is only meant to display data, there are no input controls (buttons etc...) only output controls (labels), and the callbacks are only used to update the labels at regular intervals. There are no calls made to the COM object from the UI, that means if the COM object doesn't return after the callback, that is when it blocks (in a sleep call fi) without pumping the message queue, you are screwed, and you have to resort to hacks like DoEvents() to update the UI (redraw) before you return from the eventhandler. Again without seeing the source code of the COM objects it's hard to be sure for 100% , but I wouldn't be surprised it's like that.
All you have to do to get rid of the DoEvents hack, is create a separate thread initialized for STA, create an instance of the COM object and update the UI using Control.BeginIn voke.

Willy.


"Ollie Riches" <ol**********@p honeanalyser.ne t> wrote in message news:us******** ******@tk2msftn gp13.phx.gbl...
Thanks for the reply Willy,

If you should never call DoEvents() then I have to ask why was it included? I believe it is similar to including GC.Collect in that it is exposed to the public for use in extreme circumstances.

I can understand that while a message is being processed that no other message can be processed hence the name synchronous message processing.

I can give an example taken straight from the support site of the product I am using, you can probably guess the product involved in the code. I am well aware that any code published on any site is not always the correct way to solve a problem. The code in question uses the primary interop assembly that was generated by the vendor.

If you are using (primary) COM interop library are you required to initialise COM ? - as far as I am aware you do not have too.

Here is the complete winforms example, check out the method 'Display_Instru ment_Informatio n'
Cheers

Ollie Riches

"Willy Denoyette [MVP]" <wi************ *@telenet.be> wrote in message news:eg******** ******@TK2MSFTN GP10.phx.gbl...
DoEvents() should never be called nor in a COM interop scenario and not on
the UI thread. All you have to do is make sure you don't block the message
pumping/dispatching by calling functions or running code that take a long
time before yielding (~300msec. might be too long for a decent user
experience). The same thing goes for a COM callback that runs on the UI
thread, messages aren't dispatched as long as the callback code runs.
Now it's hard to tell what happens in your code without some more context
(apartment requirements of COM object) and seeing any code; What's not clear
is where you call DoEvents() on a UI thread that is not pumping, so it looks
like your code blocks the message while running in a tight loop and you call
DoEvents in the loop.

Willy.




"Ollie Riches" <ol**********@p honeanalyser.ne t> wrote in message
news:en******** ******@tk2msftn gp13.phx.gbl...
I understand the use of Application.DoE vents() to process all outstanding
messages on the message queue in a winforms application if you have long
running process on the UI thread. But can anyone explain to me why I need
to call DoEvents when I am using a COM component that calls back to into
the .Net application? - If I don't call DoEvents after receiving a callback
then sometimes no more messages are pumped, it appears that the message
pump is suspended until the call is made.

I suspect that when a callback occurs from COM into the .Net process that
it will not be guaranteed to be executed on the UI thread is this true?
( Note: I do know about updating the UI thread from a worker thread so
people pleased don't try and tell me about the 'Invoke' method on the
Control class)

Cheers

Ollie Riches


Nov 17 '05 #6
Ollie,

Any STA COM object requires the thread on which it is created to run the
message pump. It is due to the way the system serializes calls to STA COM
objects - the calls are marshalled as private Windows messages to a
dedicated hidden window, "OleMainThreadW nd" (not sure about exact spelling).
If an STA thread makes a blocking call and stops processing Windows
messages, no calls can be forwarded to any COM component in the STA
apartment the thread belongs to. Application.DoE vents forces the Framework
to process accumulated messages, thus allowing any serialized calls to
complete. Does this answer your question?

--
Sincerely,
Dmytro Lapshyn [Visual Developer - Visual C# MVP]

"Ollie Riches" <ol**********@p honeanalyser.ne t> wrote in message
news:ua******** ******@TK2MSFTN GP14.phx.gbl...
Turns out the problem was related to the threading model, it should have
been MTA not STA, with the wrong threading apartment the code required the
use of Application.DoE vents().

So the next question is - why would having the wrong thread apartment for an
unmanaged COM component cause the message pump to not work correctly and
require the use of Application.DoE vents()?
Cheers

Ollie Riches

"Ollie Riches" <ol**********@p honeanalyser.ne t> wrote in message
news:un******** ******@TK2MSFTN GP10.phx.gbl...
Thanks for the info Willy, I realised the solution after posting the reply -
its always good to talk out a problem...

Cheers

Ollie Riches
"Willy Denoyette [MVP]" <wi************ *@telenet.be> wrote in message
news:O9******** ******@TK2MSFTN GP12.phx.gbl...
Well I really don't know why DoEvents included, but it's heritage is VB so I
guess we have to look that way. Anyway there is no need ever to call
DoEvents because there is a better solution and because it's not re-entrant
safe.
Now as for this code, I can hardly be sure for 100% what's going on without
any more info on the COM library itself (would like to know it's
threadingmodel) .
What I see is that the UI is only meant to display data, there are no input
controls (buttons etc...) only output controls (labels), and the callbacks
are only used to update the labels at regular intervals. There are no calls
made to the COM object from the UI, that means if the COM object doesn't
return after the callback, that is when it blocks (in a sleep call fi)
without pumping the message queue, you are screwed, and you have to resort
to hacks like DoEvents() to update the UI (redraw) before you return from
the eventhandler. Again without seeing the source code of the COM objects
it's hard to be sure for 100% , but I wouldn't be surprised it's like that.
All you have to do to get rid of the DoEvents hack, is create a separate
thread initialized for STA, create an instance of the COM object and update
the UI using Control.BeginIn voke.

Willy.


"Ollie Riches" <ol**********@p honeanalyser.ne t> wrote in message
news:us******** ******@tk2msftn gp13.phx.gbl...
Thanks for the reply Willy,

If you should never call DoEvents() then I have to ask why was it included?
I believe it is similar to including GC.Collect in that it is exposed to the
public for use in extreme circumstances.

I can understand that while a message is being processed that no other
message can be processed hence the name synchronous message processing.

I can give an example taken straight from the support site of the product I
am using, you can probably guess the product involved in the code. I am well
aware that any code published on any site is not always the correct way to
solve a problem. The code in question uses the primary interop assembly that
was generated by the vendor.

If you are using (primary) COM interop library are you required to
initialise COM ? - as far as I am aware you do not have too.

Here is the complete winforms example, check out the method
'Display_Instru ment_Informatio n'
Cheers

Ollie Riches

"Willy Denoyette [MVP]" <wi************ *@telenet.be> wrote in message
news:eg******** ******@TK2MSFTN GP10.phx.gbl...
DoEvents() should never be called nor in a COM interop scenario and not on
the UI thread. All you have to do is make sure you don't block the message
pumping/dispatching by calling functions or running code that take a long
time before yielding (~300msec. might be too long for a decent user
experience). The same thing goes for a COM callback that runs on the UI
thread, messages aren't dispatched as long as the callback code runs.
Now it's hard to tell what happens in your code without some more context
(apartment requirements of COM object) and seeing any code; What's not
clear
is where you call DoEvents() on a UI thread that is not pumping, so it
looks
like your code blocks the message while running in a tight loop and you
call
DoEvents in the loop.

Willy.


"Ollie Riches" <ol**********@p honeanalyser.ne t> wrote in message
news:en******** ******@tk2msftn gp13.phx.gbl...
I understand the use of Application.DoE vents() to process all outstanding
messages on the message queue in a winforms application if you have long
running process on the UI thread. But can anyone explain to me why I need
to call DoEvents when I am using a COM component that calls back to into
the .Net application? - If I don't call DoEvents after receiving a
callback
then sometimes no more messages are pumped, it appears that the message
pump is suspended until the call is made.

I suspect that when a callback occurs from COM into the .Net process that
it will not be guaranteed to be executed on the UI thread is this true?
( Note: I do know about updating the UI thread from a worker thread so
people pleased don't try and tell me about the 'Invoke' method on the
Control class)

Cheers

Ollie Riches


Nov 17 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

24
3285
by: bazad | last post by:
Hi, I'd like to understand consequences of Application.DoEvents call. Does it create a new thread? Thank you
6
609
by: foldface | last post by:
Hi I am doing drag and drop between controls (listview and treeview) using mouse_event. What I am after is a book/resource to explain the behaviour below. If I do the various Win32 api calls and call Application.Run, it works. I can see dragging and dropping on the screen. If I do this:
1
5963
by: RSH | last post by:
I created a new Windows Form project and I created a simple richtextbox to write to and I am looping through a simple example but obviously the screen isn't updated it only shows the first occurance. I have used Application DoEvents in the past to update the screen which works. but for some reason in this project when i use Application.DoEvents i get the error... "DoEvents() Is not a member of DTS.Application" How do I make the...
13
10101
by: Amjad | last post by:
Hi, Is there an equivalent to the "Application.Doevents" method in modules or Windows services? I want to make a Windows service that calls a DLL. The DLL would have all my functions and it would be doing all the job, but some of the functions that I'm using require calling something like "Application.Doevents" and I can't use this because the DLL module is not an application.
2
1531
by: joeforbroke | last post by:
Background: I am helping someone debug a problem with their form that I have traced to a strange interaction between a click event handler and Application.DoEvents(). I'm trying to talk him into using mutithreading. Problem in its essence: create a simple Form with 2 buttons and a label. button1 starts a long-running counting process, button 2 stops the counting process. The
5
4578
by: james.jdunne | last post by:
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.Windows.Forms.UnsafeNativeMethods+IMsoComponentManager.FRegisterComponent(IMsoComponent component, MSOCRINFOSTRUCT pcrinfo, Int32& dwComponentID) at...
16
12925
by: Alan T | last post by:
I tried to use a thread to process a iterative execution of processes but afraid my thread is not thread-safe. If I am not using a thread, my main form will become 'white' when switch forth and fro between other applications. So now I tried Application.DoEvents(). But it seems does not help, my main form still displays as 'white' when switch between other application.
4
10929
by: Woo Mun Foong | last post by:
Hi, I have a DLL that is used to carry out some lengthly process. I would like to have something similar to DoEvents that can yield control back to Windows every now and then. Any ideas ? Thank You,
0
9489
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9298
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9906
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9885
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9737
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8737
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7286
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6562
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5329
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.