none
Calling 3rd Part Code asynchronously RRS feed

  • Question

  • I am customizing some 3rd party code. I want to call some code asynchronously which is currently not working in async/await.

    Ex :- Casting an object  - [(Root)system] boot Root and system are 3rd party code.

    Note:- This works if i run it synchronously.

    inside an async/await which throws exception, Function requires all threads to run and then null reference Exception.

    Does this means it involves UI somehow?? As i believe code involving UI cannot run asynchronously.

    If it is not UI related then how to rectify this?

    Friday, February 15, 2019 9:11 AM

All replies

  • The error you're getting is from the debugger, not the code. If you pause your code in the debugger and then try to evaluate something that requires code to execute then the debugger shows this message. It just means it cannot evalulate it until the code is unpaused.

    The null reference error is the actual runtime error you're getting. Unfortunately we don't have access to your code so we cannot explain why you'd get a null reference. The clear reason is that you have a null object. Looking at your posted code you're doing a cast. If the `system` variable isn't of type `Root` you'd get a cast exception but if it is null then whatever you assigned it to is null. You'll need to look at the callstack on the exception to see where in your code it is failing and that will point you to the instance you're referencing is null. Once there you can trace back through all the code paths to confirm that you are assigning it a (valid) value and that it is behaving correctly. Setting breakpoints help with this.

    As for a UI thing then if you reference an object that requires the UI thread on a non-UI thread then it'll eventually throw an exception. If you're in the debugger you'll get a very specific cross thread error from the debugger. That hasn't happened here but that doesn't mean once you fix the null reference error it won't. If the component you're referencing must be called on the thread that created it then you cannot reference it on any other thread. Only you and the developer of the component can know the answer to that.

    As for running code async it is pretty easy to do. Just wrap it in a Task.Run call. Either use await to wait for it (if in an async method) or use Wait() or Result to wait for it to complete.


    Michael Taylor http://www.michaeltaylorp3.net

    Friday, February 15, 2019 2:59 PM
    Moderator
  • As I said in my post above the cast successfully occurs if I run the code synchronously. The variable system is assigned a valid value and it can be casted to Root object. So nothing is null. But somehow while running it asynchronously inside async/await it fails. If i look at the stack Trace It does not say "Cross Thread error". 

    As you said only the developer can know whether it is Thread dependent or not, I guess i will have to contact the component developer.

    Just one clarity needed, If this works in a normal synchronous process and it does not work in async. Does it mean it is thread dependent? If it is not due to cross thread dependency, then what is the reason for failure? Any other possibilities?

    Friday, February 15, 2019 3:27 PM
  • For a null reference exception - no. However you haven't really clarified what `system` and `Root`are. If they are COM objects then STA/MTA come into play. In that case if you try to marshal a COM object across threads and it doesn't support it and then do a cast (which translates to a QueryInterface call) then you can get back null for the COM interface. So in that regard making something async could cause a behavior change. But for regular .NET types and interfaces this wouldn't be a problem since the runtime can cast across threads.

    Michael Taylor http://www.michaeltaylorp3.net

    Friday, February 15, 2019 3:40 PM
    Moderator
  • Thanks for the clarification. I guess that is the case with me that they are COM objetcs and does not support multi threading. As i have seen something like what u have mentioned (QueryInterface Call). 

    One more thing, How do i check if its a COM object and does not support multi threading?

    And now obviously if it is COM and does not support MTA, then I cannot run it inside async.

    Thanks a lot for your quick replies.

    Friday, February 15, 2019 4:10 PM
  • To be clear it isn't that COM doesn't support threading but that a COM class doesn't support it so it has to run in the STA. Most UI-based COM components and those written in VB tend to lean this way. Other COM classes can be called from anywhere.

    The easiest way to know if you're dealing with a COM object is to look at the .NET type. It'll have reference to COM stuff if it is a wrapper. If the COM class doesn't support multi-threading then you can access across threads but the interface has to be marshaled and calls to it have to be serialized back to the initial thread.

    If you are dealing with an STA then generally the easiest thing to do is create the component on the thread you want to run it on. That doesn't lend itself to async but doesn't mean you have to run it on the primary thread. For example if you have a UI application and need to make periodic calls that require a COM object then you can create the COM object in a separate thread (configured as an STA) and then use the COM object independent of the UI thread. Once you're done you get rid of the COM object and thread. Of course you're going to end up having to do some marshaling so it isn't trivial.

    There is a (dated) blog article that may help you with the marshaling if you need to go that route. It mentions some features added in newer OS versions that you may be able to use.


    Michael Taylor http://www.michaeltaylorp3.net

    Friday, February 15, 2019 6:04 PM
    Moderator
  • I got what you you are saying but how to implement Marshaling?

    Is there any example you can provide in c#??

    Thanks

    Monday, February 25, 2019 8:48 AM
  • It depends upon whether you're dealing with a single thread COM object or not. MSDN documentation on this topic is here

    My personal recommendation is to simply move the COM object (declaration and new) into the thread where you need it so you don't have to mess with any of this. It is the simplest solution for non-ActiveX controls.


    Michael Taylor http://www.michaeltaylorp3.net

    Monday, February 25, 2019 2:52 PM
    Moderator
  • Hi

    Is your problem solved? If so, please post "Mark as answer" to the appropriate answer , so that it will help other members to find solution quickly if they faces similar issue.

    Best Regards,

    Jack


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Friday, March 1, 2019 7:38 AM
    Moderator
  • I have created a new STA thread and did all all the stuff inside new thread but still gets the following error:-

    Unable to cast COM object of type 'System.__ComObject' to interface type 'IMSRelation.IJAssocRelation'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{609567C0-4ED3-11D1-B2B9-080036024603}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).

    Are there any other suggestions?

    Monday, March 4, 2019 6:06 AM
  • OK that is a different exception. The error you're getting now is that the COM class for which you're doing the cast doesn't implement the interface you have requested. You need to be casting the object to an interface. In your original code it was using `Root`. Is that a COM interface implemented by the object. Note that you cannot use a COM class for the cast, it must be an interface.

    Michael Taylor http://www.michaeltaylorp3.net

    Monday, March 4, 2019 2:42 PM
    Moderator