I'm working on a big legacy project with a lot of libraries and layers. I added some functionality to a common library and declared some async methods. In order to implement the asynchronous approach end-to-end I had to refactor some existing methods to convert them to async. This lead to a chain of modifications, which have also involved changing a method call in an old webform (aspx). The method called by the webform is now async but, unfortunately, I can't use "async" or "await" inside the webform code-behind class because there are COM references within the webform and therefore it has to have "async=false".
In the webform there is a method which updates the UI with the output from the method which is now async. I have tried calling my async method using Task.Run.
This is how it used to be:
var result = mySyncronousMethod();
updateUI(result);
This is how it is now:
var result = Task.Run(async () => await commonLib.myAsyncMethod()).Result;
updateUI(result);
Unfortunately, the code path that is triggered by myAsyncMethod() includes some old COM calls somewhere along the lines. When the code hits these, it errors with "Object reference..." exceptions. Interestingly, if I debug the COM code (using VB6 Studio - ... I know, it's ancient!) it all works perfectly. I believe it's because of the late binding.
If I just call:
Task.Run(async () => await myAsyncMethod());
and don't update the UI, it all works. The async method runs and does what it needs to do with no errors. I just can't use the output to do anything in the UI, because the UI thread continues and completes the page lifecycle (as expected). The error appears only if I call ".Result".
I spent a lot of time trying to figure out how to do this. In the end I refactored the code to remove the COM references altogether, replacing them with .NET code. This solved all my problems. From the web form I can now use:
var result = Task.Run(async () => await commonLib.myAsyncMethod()).Result;
updateUI(result);
My question is: is there a way in which this can work without having to remove the COM references?
I hope this all makes sense. Any ideas would be greatly appreciated.
Update 18/09/2019
I tried reproducing this issue in this repo https://github.com/erionpc/AsyncCOM
It's really hard to isolate the code but this is the best I could do. However, the issue can't be reproduced in this sample solution. The only difference is that I had to add a key in the web.config app settings
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="false" />
otherwise I would get an error. The original web form doesn't have this.