Felix Collins
2009-03-27 02:35:04 UTC
Hi All,
I originally posted this to *.directx.managed but got no response.
Hopefully someone else using directshow has run into this and can help
me.
I've got a tricky problem in my C# application that uses Directshow.
What happens is the user clicks a button which causes a cascade of
calls that ends in a call to a Directshow method,
IFilterGraph2.AddSourceFilterForMoniker(). At the point of the call
to AddSourceFilterForMoniker, the next button click message starts to
get processed before the call has returned (assume here that the user
is clicking on the buttons quite fast). I assume this is because the
Directshow object is pumping all messages instead of just the COM
ones. I'm not sure if this is a bug but is does cause reentrancy in
the windows forms event handlers which are written assuming single
threaded operation.
Does anyone have any ideas about how to fix
it?
I'm considering the following solution:
1. Define a global counting semaphore.
2. Override the message loop and filter out mouse and keyboard
messages while the semaphore is greater than zero.
3. Before any Directshow call, increment the semaphore.
4. On the Directshow call returning, decrement the semaphore.
This will prevent reentrant user input events but won't stop other
windows messages being processed out of turn like timers etc.
Example call stack shown below with irrelevant stack frames removed.
Thanks for your help,
Felix
< Irrelevant code removed here that leads to a crash caused by the
reentrancy>
System.Windows.Forms.Control.OnClick(System.EventArgs e)
DevExpress.XtraEditors.BaseButton.OnClick(System.EventArgs e)
DevExpress.XtraEditors.BaseButton.OnMouseUp
(System.Windows.Forms.MouseEventArgs e)
System.Windows.Forms.Control.WmMouseUp(ref
System.Windows.Forms.Message m, System.Windows.Forms.MouseButtons
button, int clicks) System.Windows.Forms.Control.WndProc(ref
System.Windows.Forms.Message m)
DevExpress.Utils.Controls.ControlBase.WndProc(ref
System.Windows.Forms.Message m)
System.Windows.Forms.Control.ControlNativeWindow.OnMessage(ref
System.Windows.Forms.Message m)
System.Windows.Forms.Control.ControlNativeWindow.WndProc(ref
System.Windows.Forms.Message m)
System.Windows.Forms.NativeWindow.Callback(System.IntPtr hWnd, int
msg, System.IntPtr wparam, System.IntPtr lparam) [Native to
Managed Transition] [Managed to Native Transition]
Intranel.Video.View.Windows.FilterGraphTools.AddFilterByName
(DirectShowLib.IGraphBuilder graphBuilder, <
< More irrelevant application code deleted here - AddFilterByName
(above) calls AddSourceFilterForMoniker>
System.Windows.Forms.Control.WmMouseUp(ref
System.Windows.Forms.Message m, System.Windows.Forms.MouseButtons
button, int clicks) System.Windows.Forms.Control.WndProc(ref
System.Windows.Forms.Message m)
DevExpress.Utils.Controls.ControlBase.WndProc(ref
System.Windows.Forms.Message m)
System.Windows.Forms.Control.ControlNativeWindow.OnMessage(ref
System.Windows.Forms.Message m)
System.Windows.Forms.Control.ControlNativeWindow.WndProc(ref
System.Windows.Forms.Message m)
System.Windows.Forms.NativeWindow.Callback(System.IntPtr hWnd, int
msg, System.IntPtr wparam, System.IntPtr lparam) [Native to
Managed Transition] [Managed to Native Transition]
System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop
(int dwComponentID, int reason, int pvLoopData)
System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(int
reason, System.Windows.Forms.ApplicationContext context)
System.Windows.Forms.Application.ThreadContext.RunMessageLoop(int
reason, System.Windows.Forms.ApplicationContext context)
System.Windows.Forms.Application.Run(System.Windows.Forms.Form
mainForm) Videoscribe.UI.Workspaces.VideoscribeViewEngine.Start
(Intranel.Workspaces.IWorkbench workbench) Line 77 C#
CaptureStudio.Program.Main() Line 194 C#
[Native to Managed Transition] [Managed to Native
Transition] System.AppDomain.ExecuteAssembly(string
assemblyFile, System.Security.Policy.Evidence assemblySecurity, string
[] args)
Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly
() System.Threading.ThreadHelper.ThreadStart_Context(object
state) System.Threading.ExecutionContext.Run
(System.Threading.ExecutionContext executionContext,
System.Threading.ContextCallback callback, object state)
System.Threading.ThreadHelper.ThreadStart()
I originally posted this to *.directx.managed but got no response.
Hopefully someone else using directshow has run into this and can help
me.
I've got a tricky problem in my C# application that uses Directshow.
What happens is the user clicks a button which causes a cascade of
calls that ends in a call to a Directshow method,
IFilterGraph2.AddSourceFilterForMoniker(). At the point of the call
to AddSourceFilterForMoniker, the next button click message starts to
get processed before the call has returned (assume here that the user
is clicking on the buttons quite fast). I assume this is because the
Directshow object is pumping all messages instead of just the COM
ones. I'm not sure if this is a bug but is does cause reentrancy in
the windows forms event handlers which are written assuming single
threaded operation.
Does anyone have any ideas about how to fix
it?
I'm considering the following solution:
1. Define a global counting semaphore.
2. Override the message loop and filter out mouse and keyboard
messages while the semaphore is greater than zero.
3. Before any Directshow call, increment the semaphore.
4. On the Directshow call returning, decrement the semaphore.
This will prevent reentrant user input events but won't stop other
windows messages being processed out of turn like timers etc.
Example call stack shown below with irrelevant stack frames removed.
Thanks for your help,
Felix
< Irrelevant code removed here that leads to a crash caused by the
reentrancy>
System.Windows.Forms.Control.OnClick(System.EventArgs e)
DevExpress.XtraEditors.BaseButton.OnClick(System.EventArgs e)
DevExpress.XtraEditors.BaseButton.OnMouseUp
(System.Windows.Forms.MouseEventArgs e)
System.Windows.Forms.Control.WmMouseUp(ref
System.Windows.Forms.Message m, System.Windows.Forms.MouseButtons
button, int clicks) System.Windows.Forms.Control.WndProc(ref
System.Windows.Forms.Message m)
DevExpress.Utils.Controls.ControlBase.WndProc(ref
System.Windows.Forms.Message m)
System.Windows.Forms.Control.ControlNativeWindow.OnMessage(ref
System.Windows.Forms.Message m)
System.Windows.Forms.Control.ControlNativeWindow.WndProc(ref
System.Windows.Forms.Message m)
System.Windows.Forms.NativeWindow.Callback(System.IntPtr hWnd, int
msg, System.IntPtr wparam, System.IntPtr lparam) [Native to
Managed Transition] [Managed to Native Transition]
Intranel.Video.View.Windows.FilterGraphTools.AddFilterByName
(DirectShowLib.IGraphBuilder graphBuilder, <
< More irrelevant application code deleted here - AddFilterByName
(above) calls AddSourceFilterForMoniker>
System.Windows.Forms.Control.WmMouseUp(ref
System.Windows.Forms.Message m, System.Windows.Forms.MouseButtons
button, int clicks) System.Windows.Forms.Control.WndProc(ref
System.Windows.Forms.Message m)
DevExpress.Utils.Controls.ControlBase.WndProc(ref
System.Windows.Forms.Message m)
System.Windows.Forms.Control.ControlNativeWindow.OnMessage(ref
System.Windows.Forms.Message m)
System.Windows.Forms.Control.ControlNativeWindow.WndProc(ref
System.Windows.Forms.Message m)
System.Windows.Forms.NativeWindow.Callback(System.IntPtr hWnd, int
msg, System.IntPtr wparam, System.IntPtr lparam) [Native to
Managed Transition] [Managed to Native Transition]
System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop
(int dwComponentID, int reason, int pvLoopData)
System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(int
reason, System.Windows.Forms.ApplicationContext context)
System.Windows.Forms.Application.ThreadContext.RunMessageLoop(int
reason, System.Windows.Forms.ApplicationContext context)
System.Windows.Forms.Application.Run(System.Windows.Forms.Form
mainForm) Videoscribe.UI.Workspaces.VideoscribeViewEngine.Start
(Intranel.Workspaces.IWorkbench workbench) Line 77 C#
CaptureStudio.Program.Main() Line 194 C#
[Native to Managed Transition] [Managed to Native
Transition] System.AppDomain.ExecuteAssembly(string
assemblyFile, System.Security.Policy.Evidence assemblySecurity, string
[] args)
Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly
() System.Threading.ThreadHelper.ThreadStart_Context(object
state) System.Threading.ExecutionContext.Run
(System.Threading.ExecutionContext executionContext,
System.Threading.ContextCallback callback, object state)
System.Threading.ThreadHelper.ThreadStart()