سؤال

I have a native desktop application (no /ZW used) and a DLL built with /ZW. The DLL serves to create WinRT toasts via ToastNotificationManager.

I have a C++/CX class in the DLL which receives events for toast clicks. This all works fine; however, the events come in on a worker thread. Somehow I need to get a call onto the main thread. What is the best way to accomplish this?

I have tried setting the attributes

[Threading(ThreadingModel::STA)]
[MarshalingBehavior(MarshalingType::Standard)]

for my C++/CX class, but still the events are called on a worker thread. I have tried adding [Platform::STAThread] to my main method in the desktop application. I have tried ::RoInitialize(RO_INIT_SINGLETHREADED); at the start of the app.

Am I going down the wrong path here? Do I need to use something like:

var dispatcher = Windows.UI.Core.CoreWindow.GetForCurrentThread().Dispatcher; // from UI thread
dispatcher.RunAsync // from worker thread?

except in C++/CX?

edit: Windows.UI.Core.CoreWindow.GetForCurrentThread() returns null when I query it on my UI thread. The UI thread is MFC based.

edit2: I have been playing around with Platform::Agile. I setup an agile pointer on the main thread, pointing to my C++/CX class, then attempt to call it in the event handler on the worker thread. In agile.cpp it looks like its trying to get the proxy, but fails with hresult REGDB_E_IIDNOTREG Interface not registered. It seems like I'm close; somehow I need to register my C++/CX class. In plain COM I believe this would be with the Global Interface Table. Not sure how this works for C++/CX though.. it's not automatic?

هل كانت مفيدة؟

المحلول

You're not going to be able to use the CoreDispatcher from a desktop application, it requires CoreWindow and CoreWindow isn't enabled for desktop applications.

Why not simply post a custom window message from your event handler to get back to the UI thread? Under the covers, that's all that CoreDispatcher is doing (it's also what COM does to get back to an STA window).

If you absolutely must get COM cross apartment marshaling working for your classes, you're going to have to register proxy/stub DLLs for all your interfaces. That means you need to use the WINMDIDL tool to generate an IDL file from the winmd file that's associated with your C++/CX component. You then need to run that IDL file through the MIDL tool with the /winrt command line switch. That will create a proxy/stub DLL, you can then register that proxy/stub DLL just like you'd register any other COM proxy/stub DLL.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top