locked
Creating VS Tool Window From a Thread RRS feed

  • Question

  • I have some third party control that consumes lot of  UI therad time. It is hosted in a VS tool window. I  created another STA thread  that pumps messages and try to create this toolwindow from there. But it got failed.

    Actually i called ShowToolWindow() from this thread and inside the function it will try to FindToolWindow()

    Please suggest me a way to do this if some one has  experience in hosting tool window from a thread other than UI thread.




    Monday, April 15, 2013 6:11 PM

Answers

  • Looks like some param is not marked as 'unique' in IDL thus the stub won't accept null as an input value. Not much you can do there, though you could get around it simply by constructing your window's outer content holder object on the normal UI thread, and inside its ctor kick off the other thread to construct the 'expensive control'.

    I suspect you will have a  lot of difficulty pulling this off. Depending on what your UI tree looks like this will range from annoying (if it is all WPF top to bottom) to horrifically complicated (if there is ANY Win32 HWND anywhere in the tree).

    There is a brief covering of this here: http://blogs.msdn.com/b/dwayneneed/archive/2007/04/26/multithreaded-ui-hostvisual.aspx

    Note this bit specifically: There are some limitations: namely that the UI owned by the worker threads do not receive input events.

    This means no mouse, no keyboard interaction, which likely is a no-go for a toolwindow.



    Wednesday, April 17, 2013 8:41 PM

All replies

  • You would need to be more specific than 'it failed'. How did it fail? It threw an exception? What was the exception?

    Do know what you are attempting is extremely difficult? There are loads of synchronization problems, you have the possibility of deadlocking VS if you aren't fairly knowledgeable about cross-thread communication, you have to manually propagate some input messages, etc...


    Monday, April 15, 2013 9:02 PM
  • CommandID toolwndCommandID = new CommandID(GuidList.guidVSPackage2CmdSet, (int)PkgCmdIDList.cmdidMyTool); MenuCommand menuToolWin = new MenuCommand(ShowToolWindowFromThread, toolwndCommandID); mcs.AddCommand( menuToolWin );

    private void ShowToolWindowFromThread(object sender, EventArgs e)
            {
                var thread = new Thread(()=>
                                               {
                                                   ShowToolWindow(sender, e);
                                                   Application.Run();
    
                                                   
                                               });
                thread.SetApartmentState(ApartmentState.STA);
                thread.Start();
            }
     private void ShowToolWindow(object sender, EventArgs e)
            {
                // Get the instance number 0 of this tool window. This window is single instance so this instance
                // is actually the only one.
                // The last flag is set to true so that if the tool window does not exists it will be created.
                ToolWindowPane window = this.FindToolWindow(typeof(MyToolWindow), 0, true);
                if ((null == window) || (null == window.Frame))
                {
                    throw new NotSupportedException(Resources.CanNotCreateWindow);
                }
                IVsWindowFrame windowFrame = (IVsWindowFrame)window.Frame;
                Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(windowFrame.Show());
            }

    In this Line

    ToolWindowPane window = this.FindToolWindow(typeof(MyToolWindow), 0, true);

    It throws an Exception "A null reference pointer was passed to the stub. (Exception from HRESULT: 0x800706F4)"

    This is the call Stack

       at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)
       at System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(Int32 errorCode)
       at Microsoft.VisualStudio.Shell.Package.CreateToolWindow(Type toolWindowType, Int32 id, ProvideToolWindowAttribute tool)
       at Microsoft.VisualStudio.Shell.Package.CreateToolWindow(Type toolWindowType, Int32 id)
       at Microsoft.VisualStudio.Shell.Package.FindToolWindow(Type toolWindowType, Int32 id, Boolean create, ProvideToolWindowAttribute tool)
       at Microsoft.VisualStudio.Shell.Package.FindToolWindow(Type toolWindowType, Int32 id, Boolean create)
       at Company.VSPackage2.VSPackage2Package.ShowToolWindow(Object sender, EventArgs e) in c:\users\X\documents\visual studio 2010\Projects\VSPackage2\VSPackage2\VSPackage2Package.cs:line 61
       at Company.VSPackage2.VSPackage2Package.<>c__DisplayClass1.<ShowToolWindowFromThread>b__0() in c:\users\X\documents\visual studio 2010\Projects\VSPackage2\VSPackage2\VSPackage2Package.cs:line 99
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()


    • Edited by jo.kply Wednesday, April 17, 2013 7:49 PM Removing personal info
    Wednesday, April 17, 2013 7:47 PM
  • Looks like some param is not marked as 'unique' in IDL thus the stub won't accept null as an input value. Not much you can do there, though you could get around it simply by constructing your window's outer content holder object on the normal UI thread, and inside its ctor kick off the other thread to construct the 'expensive control'.

    I suspect you will have a  lot of difficulty pulling this off. Depending on what your UI tree looks like this will range from annoying (if it is all WPF top to bottom) to horrifically complicated (if there is ANY Win32 HWND anywhere in the tree).

    There is a brief covering of this here: http://blogs.msdn.com/b/dwayneneed/archive/2007/04/26/multithreaded-ui-hostvisual.aspx

    Note this bit specifically: There are some limitations: namely that the UI owned by the worker threads do not receive input events.

    This means no mouse, no keyboard interaction, which likely is a no-go for a toolwindow.



    Wednesday, April 17, 2013 8:41 PM