Quantcast
Channel: Visual Studio Integrate forum
Viewing all articles
Browse latest Browse all 4410

Can't get OleMenuCommandService asynchronously when implementing IAsyncLoadablePackageInitialize

$
0
0

I want to add support for Visual Studio 2019 to a package that until now was auto loading synchronously. From Improving the responsiveness of critical scenarios by updating auto load behavior for extensions, I understand, I can't do that anymore, and will need to allow for asynchronous loading. Since I still need to support Visual Studio 2013, I tried the approach suggested in the sample at Visual Studio 2013 backwards compatible async package

The sample works as explained, and I adopted it in my package, but I am not able to get OleMenuCommandService asynchronously, in a similar way the sample gets hold of IVsUIShell.

public IVsTask Initialize(IAsyncServiceProvider asyncServiceProvider, IProfferAsyncService pProfferService, IAsyncProgressCallback pProgressCallback)
        {
            ...
            return ThreadHelper.JoinableTaskFactory.RunAsync<object>(async () =>
            {
                ...
                await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
                IVsUIShell shellService = await asyncServiceProvider.GetServiceAsync<IVsUIShell>(typeof(SVsUIShell));
                OleMenuCommandService cmdService = await asyncServiceProvider.GetServiceAsync<OleMenuCommandService>(typeof(IMenuCommandService));
                this.MainThreadInitialization(shellService, isAsyncPath: true);
                ...
            }...
        }

cmdService is always null. Whereas, from my limited knowledge on asynchronous loading (will delve deeper now), seems like since we have switched to the main thread, I can get OleMenuCommandService synchronously. I see error descriptions such as these, which seem to imply, it's okay.

System.InvalidOperationException: Due to high risk of deadlock you cannot call GetService from a background thread in an AsyncPackage derived class. You should instead call GetServiceAsync (without calling Result or Wait on the resultant Task object) or switch to the UI thread with the JoinableTaskFactory.SwitchToMainThreadAsync method before calling GetService.

public IVsTask Initialize(IAsyncServiceProvider asyncServiceProvider, IProfferAsyncService pProfferService, IAsyncProgressCallback pProgressCallback) { ... return ThreadHelper.JoinableTaskFactory.RunAsync<object>(async () => { ... await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
OleMenuCommandService cmdService = this.GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
}... }

And that works. Is this safe? What is the right way to get OleMenuCommandService with the Visual Studio 2013 backwards compatible async package sample?





Viewing all articles
Browse latest Browse all 4410

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>