Closed heroboy closed 2 months ago
This example program does not initialize the MTA in the process. The background tasks therefore run outside the MTA and the "you didn't initialize COM" error is raised.
The call to foo
works around this issue because the implementation of StorageFolder::GetFolderFromPathAsync has a side effect of initializing the MTA in the process.
I think the appropriate fix would be to have your code initialize the MTA before it tries to use it. One way that can be done is by calling CoIncrementMTAUsage. Simply call that before the call to bar
and the crash is avoided.
Thank you. I had never think apartment is a property of process. I tested:
std::thread{ []() {
winrt::init_apartment();
::Sleep(10000);
} }.detach();
std::thread{ []() {
auto type = winrt::impl::get_apartment_type();
printf("%d\n",type.first);
} }.join();
I think once a thread is initialized as MTA. All thread not initialized will be considered as MTA.
But I find that initialized with single threaded will also make the ContextCallback success.
void test()
{
winrt::com_ptr<IContextCallback> ctx;
CoGetObjectContext(IID_IContextCallback, ctx.put_void());
assert(ctx);
TrySubmitThreadpoolCallback([](PTP_CALLBACK_INSTANCE pci, PVOID p) {
auto x = winrt::impl::get_apartment_type();
winrt::com_ptr<IContextCallback> ctx;
*ctx.put_void() = p;
winrt::init_apartment(winrt::apartment_type::single_threaded);
ComCallData data;
HRESULT hr = ctx->ContextCallback([](ComCallData*) {
return S_OK;
}, &data, IID_ICallbackWithNoReentrancyToApplicationSTA, 5, nullptr);
printf("[%d]hr=%d\n", GetCurrentThreadId(), hr);
}, ctx.detach(), 0);
}
Version
C++/WinRT v2.0.220110.5
Summary
No response
Reproducible example
Expected behavior
no crash.
Actual behavior
crash at
co_await ctx;
with 'CoInitialize has not been called.'Additional comments
Uncomment the
foo()
, await any async windows runtime function, and laterco_await ctx
will no longer crash. Or callwinrt::init_apartment()
afterwinrt::resume_background()