S
Stephen Rice
Hi,
I have a periodic problem which I am having a real time trying to sort.
Background:
An MDI VB app with a DB on SQL 2000.
I have wrapped all the DB access into an object which spawns a thread to
access the database and then displays a modal dialog which allows the user
to cancel the task, if it is taking longer than they want, and shows them a
display of how long the query has been running so far.
I have been very careful (I think!) to make sure that the UI is only ever
updated from the main UI thread. I pass status info from the SQL therad to
the UI thread through a System.Threading.AutoResetEvent.
A system.windows.forms.timer runs in the Modal form to update a textbox with
the amount of time it has been there and to check the 'SQL finished' event
above.
Everything work fine 99.9% of the time BUT, very occasionally, I get an odd
situation in InitializeComponent in the modal form.
As far as I can ascertain (sorry, that should be, totally guess!), when the
timer is enabled, it does not 'see' the containing forms message loop and so
it instantiates one itself (?). This new message loop 'sees' messages in the
MDI's queue including the pending message currently being processed which
caused this whole event to occur (stay with me here!)
I think that this makes much more sense in the context of a real stack
trace:
Stack Trace: at System.Data.SqlClient.SqlCommand.ValidateCommand(String
method, Boolean executing)
at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior
cmdBehavior, RunBehavior runBehavior, Boolean returnStream)
at System.Data.SqlClient.SqlCommand.ExecuteReader()
at Ideal.clsDBThread.SQLFetchThread()
Current Stack: at System.Environment.GetStackTrace(Exception e)
at System.Environment.GetStackTrace(Exception e)
at System.Environment.get_StackTrace()
at Ideal.basUtility.LogError(Exception e, String strUserMsg)
at Ideal.clsDatabase.SQLFetch(String strCommand)
at Ideal.clsDatabase.TryEditLock(Int32 iDealID)
5 at Ideal.frmDeal.cmdEdit_Click(Object sender, EventArgs e)
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons
button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg,
IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at
System.Windows.Forms.ComponentManager.System.Windows.Forms.UnsafeNativeMetho
ds+IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason,
Int32 pvLoopData)
at System.Windows.Forms.ThreadContext.RunMessageLoopInner(Int32 reason,
ApplicationContext context)
4 at System.Windows.Forms.ThreadContext.RunMessageLoop(Int32 reason,
ApplicationContext context)
3 at System.Windows.Forms.Timer.set_Enabled(Boolean value)
at System.Windows.Forms.Timer.set_Interval(Int32 value)
2 at Ideal.frmDBExec.InitializeComponent()
at Ideal.frmDBExec..ctor()
at Ideal.clsDatabase.SQLFetch(String strCommand)
at Ideal.clsDatabase.TryEditLock(Int32 iDealID)
1 at Ideal.frmDeal.cmdEdit_Click(Object sender, EventArgs e)
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons
button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg,
IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at
System.Windows.Forms.ComponentManager.System.Windows.Forms.UnsafeNativeMetho
ds+IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason,
Int32 pvLoopData)
at System.Windows.Forms.ThreadContext.RunMessageLoopInner(Int32 reason,
ApplicationContext context)
at System.Windows.Forms.ThreadContext.RunMessageLoop(Int32 reason,
ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at Ideal.basMain.Main()
From the bottom.
Normal appication stack (I think) with a mouse click being processed
At point (1) the routine which handles the button click is called
This calls some SQL which causes the spawned thread/Modal dialog combination
and the modal dialog (Initialisation call can be seen at point 2)
Within this initialisation the timer interval gets set which in turn enables
the timer (point 3). All normal so far
Then:
At point (4), within the timer enable, there is a call to RunMessageLoop
which (I think) hooks onto the MDI's context and picks up the same mouse
click that we are currently processing and recalls the button click routine!
(point 5)
Any help or pointers to help would be VERY VERY apprieciated
Thanks in advance
Stephen
I have a periodic problem which I am having a real time trying to sort.
Background:
An MDI VB app with a DB on SQL 2000.
I have wrapped all the DB access into an object which spawns a thread to
access the database and then displays a modal dialog which allows the user
to cancel the task, if it is taking longer than they want, and shows them a
display of how long the query has been running so far.
I have been very careful (I think!) to make sure that the UI is only ever
updated from the main UI thread. I pass status info from the SQL therad to
the UI thread through a System.Threading.AutoResetEvent.
A system.windows.forms.timer runs in the Modal form to update a textbox with
the amount of time it has been there and to check the 'SQL finished' event
above.
Everything work fine 99.9% of the time BUT, very occasionally, I get an odd
situation in InitializeComponent in the modal form.
As far as I can ascertain (sorry, that should be, totally guess!), when the
timer is enabled, it does not 'see' the containing forms message loop and so
it instantiates one itself (?). This new message loop 'sees' messages in the
MDI's queue including the pending message currently being processed which
caused this whole event to occur (stay with me here!)
I think that this makes much more sense in the context of a real stack
trace:
Stack Trace: at System.Data.SqlClient.SqlCommand.ValidateCommand(String
method, Boolean executing)
at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior
cmdBehavior, RunBehavior runBehavior, Boolean returnStream)
at System.Data.SqlClient.SqlCommand.ExecuteReader()
at Ideal.clsDBThread.SQLFetchThread()
Current Stack: at System.Environment.GetStackTrace(Exception e)
at System.Environment.GetStackTrace(Exception e)
at System.Environment.get_StackTrace()
at Ideal.basUtility.LogError(Exception e, String strUserMsg)
at Ideal.clsDatabase.SQLFetch(String strCommand)
at Ideal.clsDatabase.TryEditLock(Int32 iDealID)
5 at Ideal.frmDeal.cmdEdit_Click(Object sender, EventArgs e)
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons
button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg,
IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at
System.Windows.Forms.ComponentManager.System.Windows.Forms.UnsafeNativeMetho
ds+IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason,
Int32 pvLoopData)
at System.Windows.Forms.ThreadContext.RunMessageLoopInner(Int32 reason,
ApplicationContext context)
4 at System.Windows.Forms.ThreadContext.RunMessageLoop(Int32 reason,
ApplicationContext context)
3 at System.Windows.Forms.Timer.set_Enabled(Boolean value)
at System.Windows.Forms.Timer.set_Interval(Int32 value)
2 at Ideal.frmDBExec.InitializeComponent()
at Ideal.frmDBExec..ctor()
at Ideal.clsDatabase.SQLFetch(String strCommand)
at Ideal.clsDatabase.TryEditLock(Int32 iDealID)
1 at Ideal.frmDeal.cmdEdit_Click(Object sender, EventArgs e)
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons
button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg,
IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at
System.Windows.Forms.ComponentManager.System.Windows.Forms.UnsafeNativeMetho
ds+IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason,
Int32 pvLoopData)
at System.Windows.Forms.ThreadContext.RunMessageLoopInner(Int32 reason,
ApplicationContext context)
at System.Windows.Forms.ThreadContext.RunMessageLoop(Int32 reason,
ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at Ideal.basMain.Main()
From the bottom.
Normal appication stack (I think) with a mouse click being processed
At point (1) the routine which handles the button click is called
This calls some SQL which causes the spawned thread/Modal dialog combination
and the modal dialog (Initialisation call can be seen at point 2)
Within this initialisation the timer interval gets set which in turn enables
the timer (point 3). All normal so far
Then:
At point (4), within the timer enable, there is a call to RunMessageLoop
which (I think) hooks onto the MDI's context and picks up the same mouse
click that we are currently processing and recalls the button click routine!
(point 5)
Any help or pointers to help would be VERY VERY apprieciated
Thanks in advance
Stephen