COM call from component to busy object blocks indefinitely

I am getting a specific COM object (application instance) from the ROT and trying to send commands to it. The specific application does not respond to COM calls before initialization (i.e. is busy). I would like to be notified when this is the case so I can abort the operation and show a message.

When I run the command using the following code snippet from a console application I get a COMException with a message: ‘The message filter indicated that the application is busy. (Exception from HRESULT: 0x8001010A (RPC_E_SERVERCALL_RETRYLATER))’

    try {
        comObject.someMethod();
    }
    catch (COMException) {
        // HRESULT:0x08001010A error
    }

However, I am also trying to run this from a Grasshopper plugin and in this case, the program blocks indefinitely on the comObject.someMethod() line. I don’t know where to start troubleshooting this issue and if possible, have the exception show up in the plugin as well. Any ideas?

Hello,

there are usually two possibilities. Either the application you are COM-interfacing to, is already started (with an running COM server). Or the application needs to start first. Now usually a COM interface is kind of simple and does not inform you about when this is done. So there is usually no feedback system.

So the usual approach here is to poll the Application state until its ready to be used. How to get this information depends on the interface implementation.

I think in Grasshopper it is fine to simply block the process until a COM service is ready to be used or until a time-out is reached. There is no point in unblocking the UI, because you can’t do anything meaningful anyways. Maybe you already trigger an COM start of your application after your Plugin loads.

If you decide to poll asynchronous, then things get a bit more complicated. But a good way in doing so is to do this in the background and assert in each component if the COM interface is visible and ready to use. If not your components simply fail immediately.

You might also inform the user if you have a time out issue and give the opportunity to manually trigger a reconnection.
There are plenty ways of doing so, but maybe a custom menu item in GH Menu, or a dedicated view or a dedicated component to deal with connecting to the COM interface is required, so that you handle and inform the user about the COM connection.

The OP was about a problem of a different nature. The issue is not that the thread is blocked, but that the COM message that is normally processed by a console app does not appear in Grasshopper. The COM server sends the message, but Grasshopper does not get it and blocks the thread (I do not know with what).

Grasshopper seems to have an inherent issue with the message loop which has probably manifested in this case with the COM message RPC_E_SERVERCALL_RETRYLATER never getting processed.

I have also found another post here where the user had an issue with async\await which I also observed while trying to make my COM calls async so I could put a maximum timeout on them. If you try to run an async task and wait for it’s result (so block the thread on purpose) Grasshopper will forever hang even if the task should complete.

By using an async Task with the ConfigureAwait(false) workaround, I could make Grasshopper successfully get the RPC_E_SERVERCALL_RETRYLATER COM message instead of blocking Grasshopper’s thread. Something like that:

var asyncTask = getCOMResultsAsync();
asyncTask.Wait();
List<COMResult> comResults = asyncTask.Result;

async Task<List<COMResult>> getCOMResultsAsync() {
    var t = await Task<List<COMResult>>.Factory.StartNew((comResults) => _getCOMResults(), null).ConfigureAwait(false);
    return t;
}

I think without any code involved its hard to tell what the problem is. My previous post was pointing on the polling aspect from the caller side. I think this async snippet has nothing to do with particular issue. If you miss exception or messages, it also possible that you simply have issue in dealing with multi-threaded code. I think my point here was to implement a polling logic. For such logic, its not necessary to work multi-threaded, but it gives many advantages. You should not underestimate that Console Apps are quite thread-safe from scratch, while in GUI applications like Rhino, this requires some experience with thread synchronisation. Technically I would assume you can make any COM interface run-able in Grasshopper. There is nothing fancy here. If error messages are swallowed, then this is possible. But I don’t think this is the problem here. Do you know the Visual Studio Profiler? There is a lot of tooling provided by Microsoft which can help you to investigate these problems further.

Just to clarify, if by polling you mean synchronous COM calls, this is exactly what does not work. I did not use any thread logic or async/await to begin with, but to circumvent the issue.

The original issue was that if in normal plain synchronous code I sent a COM command to the server that was busy, the server sent the RPC_E_SERVERCALL_RETRYLATER message back, but in the Grasshopper code I would never get anything and it would block forever.

Using the code snippet above (important: with ConfigureAwait(false) otherwise it will also block forever), my Grasshopper plugin now gets the RPC_E_SERVERCALL_RETRYLATER message and throws an exception normally.

It might have something to do with Grasshopper/Rhino intercepting the message and not propagating it to my component. I am not sure how I would investigate that using the profiler tools, but I will do some research.