is there a better way to handle RPC_E_CALL_REJECTED exceptions when doing visual studio automation?

后端 未结 4 529
傲寒
傲寒 2021-01-01 03:48

this is what I\'m currently doing:

    protected void setupProject()
    {
        bool lbDone = false;
        int liCount = 0;
        while (!lbDone &         


        
相关标签:
4条回答
  • 2021-01-01 04:01

    I was getting the same error using C# to read/write to Excel. Oddly, it worked in debug mode but not on a deployed machine. I simply changed the Excel app to be Visible, and it works properly, albeit about twice as slow. It is annoying to have an Excel app open and close dynamically on your screen, but this seems to be the simplest work-around for Excel.

    Microsoft.Office.Interop.Excel.Application oApp = new ApplicationClass();
    oApp.Visible = true;
    oApp.DisplayAlerts = false;
    
    0 讨论(0)
  • 2021-01-01 04:02

    There is a solution on this MSDN page: How to: Fix 'Application is Busy' and 'Call was Rejected By Callee' Errors. It shows how to implement a COM IOleMessageFilter interface so that it will automatically retry the call.

    0 讨论(0)
  • 2021-01-01 04:03

    I didn't have much luck with the recommended way from MSDN, and it seemed rather complicated. What I have done is to wrap up the re-try logic, rather like in the original post, into a generic utility function. You call it like this:

    Projects projects = Utils.call( () => (m_dteSolution.Projects) );
    

    The 'call' function calls the function (passed in as a lambda expression) and will retry if necessary. Because it is a generic function, you can use it to call any EnvDTE properties or methods, and it will return the correct type.

    Here's the code for the function:

    public static T call<T>(Func<T> fn)
    {
        // We will try to call the function up to 100 times...
        for (int i=0; i<100; ++i)
        {
            try
            {
                // We call the function passed in and return the result...
                return fn();
            }
            catch (COMException)
            {
                // We've caught a COM exception, which is most likely
                // a Server is Busy exception. So we sleep for a short
                // while, and then try again...
                Thread.Sleep(1);
            }
        }
        throw new Exception("'call' failed to call function after 100 tries.");
    }
    

    As the original post says, foreach over EnvDTE collections can be a problem as there are implicit calls during the looping. So I use my 'call' function to get the Count proprty and then iterate using an index. It's uglier than foreach, but the 'call' function makes it not so bad, as there aren't so many try...catches around. For example:

    int numProjects = Utils.call(() => (projects.Count));
    for (int i = 1; i <= numProjects; ++i)
    {
        Project project = Utils.call(() => (projects.Item(i)));
        parseProject(project);
    }
    
    0 讨论(0)
  • 2021-01-01 04:08

    First, Hans doesn't want to say so but the best answer to "how to do this" is "don't do this". Just use separate instances of visual studio for your automation and your other work, if at all possible.

    You need to take your problem statement out somewhere you can handle the error. You can do this by using in integer index instead of foreach.

    // You might also need try/catch for this!
    int cProjectItems = pProject.ProjectItems.Length;
    for(iProjectItem = 0; iProjectItem < cProjectItems; iProjectItem++)
    {
       bool bSucceeded = false;
       while(!bSucceeded)
       {
            try{
                ProjectItem pi = pProject.ProjectItems[iProjectItem];
                // do something with pi
                bSucceeded = true;
            }catch (System.Runtime.InteropServices.COMException loE)
            {
                liCount++;
                if ((uint)loE.ErrorCode == 0x80010001)                      {
                    // RPC_E_CALL_REJECTED - sleep half sec then try again
                    System.Threading.Thread.Sleep(pDelayBetweenRetry);
                }
            }  
       }
    
    }
    
    0 讨论(0)
提交回复
热议问题