locked
VS2012 IVsSolution.GetUniqueNameOfProject problems RRS feed

  • Question

  • Hi,

    Calling IVsSolution.GetUniqueNameOfProject from a worker thread fails. It works calling the method from the main thread. Same code worked just fine on VS2012. 

    Has anyone encountered this problem? Are there any changes to this method in Vs2012

    Thanks

    Thursday, September 20, 2012 11:41 AM

All replies

  • How does it fail exactly?  That is a pretty vague :)

    Ryan

    Thursday, September 20, 2012 5:31 PM
  • Hi,

    It returns E_FAIL even if it works fine on main thread.

    Friday, September 21, 2012 5:52 AM
  • Are you sure the project is completely loaded? In 2012 there is asynchronous solution load, so not all projects are immediately loaded as they were in the past. I don't think this has to do with foreground/background thread per-se. This is a COM STA object, so when you call it on a background thread it uses a proxy and executes the actual code on the UI thread, so it always runs on the UI thread. Though there are likely timing differences between your two scenarios. Do you have a repro?

    Friday, September 21, 2012 3:03 PM
  • Yes the project is loaded. 

    <<This is a COM STA object, so when you call it on a background thread it uses a proxy and executes the actual code on the UI thread, so it always runs on the UI thread.>>

    Then it should work. Calling it on the UI thread works. It looks that the  project list for the solution is not properly loaded on the secondary thread.

    <<Do you have a repro?>>

    I'm afraid not. I have a custom project based on this http://mpfproj10.codeplex.com/. I will try to reproduce it on a simple scenario

    Monday, September 24, 2012 8:11 AM
  • Have managed to reproduce this issue on a simpler use case. Project.UniqueName throws an exception.

    Thanks

    private void MenuItemCallback(object sender, EventArgs e)
            {
              //Create worker thread.
              Company.Execute execThread = new Company.Execute();
              //Add event handler
              execThread.ExecuteCompleted += (src, arg) =>
                {
                  Debug.WriteLine("Executing event raised by thread");
                  
                  EnvDTE.DTE dte = (EnvDTE.DTE)GetService(typeof(EnvDTE.DTE));
                  EnvDTE.Solution solution = dte.Solution;
                  string fullname = solution.FullName;
                  Debug.WriteLine("Solution full name" + fullname );
                  foreach ( EnvDTE.Project project in solution.Projects )
                  {
                    //Throws System.Runtime.InteropServices.COMException exception.
                    string uniqueName = project.UniqueName;
                    Debug.WriteLine("Project unique name" + uniqueName);
                  }
                };
    
              //Start the thread
              execThread.Start();
            }

    namespace Company
    {
      public class Execute
      {
        public void Start()
        {
          Thread execThread = new Thread(() =>
          {
            try
            {
              //Counting from 1 to 1000
              int i = 0;
              do 
              {
                i++;
              } while ( i <= 1000 );
            }
            catch (System.Exception ex)
            {
              Debug.WriteLine(ex.Message);
            }
            finally
            {
              OnExecuteCompleted();
            }          
          });
    
          // Start thread
          try
          {
            execThread.SetApartmentState(ApartmentState.STA);
            execThread.Start();
          }
          catch (System.Exception)
          { 
            OnExecuteCompleted();
          } 
        }
    
        public event EventHandler ExecuteCompleted;
    
        protected virtual void OnExecuteCompleted()
        {
          try
          {
            if (null != ExecuteCompleted)
            {
              EventArgs args = new EventArgs();
              ExecuteCompleted.Invoke(this, EventArgs.Empty);
            }
          }
          catch
          {
            Debug.WriteLine("An exception occurred");
          }
       
        }
      }
    }


    Tuesday, September 25, 2012 9:57 AM
  • There is no "project list for the secondary thread", as I said your call goes through a COM proxy and thus always executes on the UI thread. I will have to debug into the repro to see where the E_FAIL is coming from, but I won't be able to do that for a couple of days as I am out of town at a conference.

    Ryan

    Tuesday, September 25, 2012 8:08 PM