none
Retry to preform COM calls from "C# .NET 2.0" to "C++ MFC" after failure

    General discussion

  • Hi,

    Coding language:

    C++ MFC, C# .NET 2.0.

    Scenario description:

    I have a few COM components which run in Single-Threaded Apartment (STA). In order to solve concurrency problem, when 2 COM components competing with a third COM component, I use Pause COM Call (PCC, see *** bellow). So, when I call from first component to the second component and at the same time call from a third component to the second component, the third component will receive “Server Busy” (all the calls are COM calls).

    In MFC, when I use COM call and get as a respond “Server Busy”, there is an automatic retry to the same call. This capability is built–in MFC.

    Here is an example:

    • We have a function X.
    • X using PCC (as in the example of PCC bellow).
    • X is part of component A.
    • We have components B (C++ MFC).
    • We have component C (C# .NET 2.0).
    • Component B performing a COM call to A->X.
    • Than, component C performing a COM call to A->X.
    The outcome is:
    • component C (C#) will be rejected by exception.
    The exceptions are:
    • Call was rejected by callee. (Exception from HRESULT: 0x80010001 (RPC_E_CALL_REJECTED))
    • Creating an instance of the COM component with CLSID {4B444154-4F4D-11D1-0510-5FD9C7A88C88} from the IClassFactory failed due to the following error: 80010001.

    The problem:
    When I am trying to do the same from C# (i.e. C# -> C++), there is no retry for the call. When I try to call from C# to C++ (COM call) and the thread is locked to COM calls by the PCC I get (of course) an exception.
    Is there a “safe” way to contact C++ thread from C# ? By safe I mean, initiating several retries from the C# side (as in MFC).
    Is it configurable in the .NET framework?

    Thanks.

    ***  PCC : Pause COM Call, is basically a COM call lock. The purpose of PCC is to block the COM calls to a component if the component is already occupied with another component => send “Server Busy” to the caller.

    This is the code for PCC:
    /* This class makes incoming COM calls to be paused and wait:
    Usage : Place it in a code block (usually short) in which you want not to be interrupted by a COM  call.*/
    
    class CPauseCOMCalls
    {
    public:
       CPauseCOMCalls()
       {
          COleMessageFilter*  pOleMessageFilter = AfxOleGetMessageFilter();
          ASSERT(pOleMessageFilter);
          if (pOleMessageFilter)
          {
             pOleMessageFilter->SetBusyReply(SERVERCALL_RETRYLATER);
             pOleMessageFilter->BeginBusyState();
          }
       }
    
       ~CPauseCOMCalls()
       {
          COleMessageFilter*  pOleMessageFilter = AfxOleGetMessageFilter();
          ASSERT(pOleMessageFilter);
          if (pOleMessageFilter)
          {
             COleMessageFilter*  pOleMessageFilter = AfxOleGetMessageFilter();
             pOleMessageFilter->EndBusyState();
          }
       }
    };
    
    This is an example for using the PCC:
    
    Func()
    {
    CPauseCOMCalls PCC;
    …
    … (func body)
    …
    }


    Thursday, August 20, 2009 11:29 AM

All replies

  • I'm fairly sure that Windows Forms already uses the COM IMessageFilter (not .NET's), I saw it used when studying its message loop.  I think it is being used to deal with interactions with the IDE in debugging mode, not quite sure.  There are no knobs to tweak to tell it not to do so.  I think you're stuck.

    Hans Passant.
    Thursday, August 20, 2009 12:11 PM
    Moderator