0

I have been able to come up with the following C++/winRT code which "almost works". I created a class with a method that returns IAsyncOperation so that I could use the co_await keyword; the method looks like this:

IAsyncOperation<StorageFile> FileDialogs::chooseFileToOpen() const
{
   FileOpenPicker picker{};
   picker.ViewMode(PickerViewMode::Thumbnail);
   picker.SuggestedStartLocation(PickerLocationId::DocumentsLibrary);
   picker.FileTypeFilter().Append(L".jpg");
   picker.FileTypeFilter().Append(L".png");

   StorageFile file = co_await picker.PickSingleFileAsync();


   co_return file;
}

Now I call this method from the click handler of a button:

void MainPage::btnUpdateSource_Click(IInspectable const & sender, 
  RoutedEventArgs const & args)
{
   FileDialogs fd{};
   auto res = fd.chooseFileToOpen();

   StorageFile file = res.get();
   auto name = file.Name();
   ///.....
}

This compiles but when the get() method is called it fires this assert:

WINRT_ASSERT(!is_sta());

So it is complaining that the apartment is single-threaded! and yet winrt::init_apartment() was called with multithreading!!

So that's where I am stuck!

Can anyone give me some insight? I am using Visual Studio 2017 version 15.7.5.

Thanks, Juan

Juan Dent
  • 439
  • 2
  • 6
  • 14
  • `get()` is a synchronous wait. To keep your UI responsive, C++/WinRT makes sure you know, when you are invoking a blocking call on the UI thread, by issuing an assertion. You'll have to get rid of the blocking call on the UI thread, e.g. by turning `btnUpdateSource_Click` into a coroutine (by having it return `IAsyncAction`, for example), and using `StorageFile file{ co_await fd.chooseFileToOpen() };` instead of the blocking call. – IInspectable Jul 23 '18 at 21:43
  • I tried to make btnUpdateSource_Click into a coroutine by making it return IAsyncAction but it produces many error messages at compile time! btnUpdateSource_Click used to return void. Any suggestions or another way to make that method a coroutine? Some of the error messages include: 'btnUpdateSource_Click': unknown override specifier (compiling source file MainPage.cpp) ocurring at the MainPage.h file in the declaration of the coroutine method... – Juan Dent Jul 24 '18 at 00:43
  • The XAML declaration for this method is: – Juan Dent Jul 24 '18 at 00:51
  • Is the event handler declared in MainPage.idl? If so, you're going to have to change that, compile the project, copy the signature from the *Generated Files\\sources* directory, and compile again. A bit of guessing here, based on the incomplete information. The full error message would certainly help. – IInspectable Jul 24 '18 at 07:40
  • Ok,I declared the event handler in MainPage.idl using fully qualified IAsyncAction, copied the signature from the generated MainPage.h and it fully compiles and runs!! Thank you! This is my first baby step into C++/WinRT – Juan Dent Jul 24 '18 at 18:28
  • You don't need to resort to IDL, but that's fine too. Here's a simpler example. https://github.com/kennykerr/cppwinrt/blob/master/Store/XamlCode/App.cpp – Kenny Kerr Jul 26 '18 at 15:22

0 Answers0