none
[UWP][C++] How do you syncronously call an AsyncShow method? RRS feed

  • Question

  • I know in C#, you declare a function/method with the async keyword then you can use the await keyword inside it.  How do you do this in VC++?  Specifically, I want to show a dialog box and block (wait) until the user clicks either the primary or secondary buttons.

    int ButtonClick(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
    {
    	ContentDialog ^dBox = ref new ContentDialog;
    
    	// Do some prep work
    
    	dBox->ShowAsync();
    
    	// Use properties to get stuff from dialog box.
    
    	delete dBox;
    }
    

    So, how do I call the ShowAsync() method and wait for it to return?

    Wednesday, September 2, 2015 5:42 PM

Answers

  • If this is the first time running around with UI programming, I can understand your frustration.

    But showing dialog boxes the "sync" way is dirty and causes a lot of issues with the control that shows that dialog, because it essentially blocks the message loops, which will cause the OS to believe the application is not responding and terminate it.

    http://stackoverflow.com/questions/361493/why-are-modal-dialog-boxes-evil

    You can use global variables to get out stuff of the lambdas.

    Please note that showing the dialog box is not really multithreaded. the UI thread will be the one processing the dialog box's message loop, but it will do so asynchronously with the main message loop, meaning neither will be blocked.

    Friday, September 4, 2015 6:42 AM
  • The model is slightly different come .net 4.5 (and winRT) and async/await.

    Instead of completely stopping the message loop, it continues to process messages that come from the OS, while still blocking user input and restricting it to the dialog that pops up. This allows applications to comply with the requirements of windows universal apps, which terminates applications that do not respond to OS messages for 10 seconds while still displaying dialog boxes.

    In fact, the whole point of async is to not block the message loop for extended periods of time.

    Whether showing that dialog is done by the UI thread or not is irrelevant. It will use synchronization contexts and from your point of view, the dialog is displayed by another thread, even if in essence it is not. This is why using a mutex does yield some results but not what you want to achieve.

    Another pitfall you should be aware of in async programming models is that something that is marked as async does not necessary create a new thread when it is called.

    http://blog.stephencleary.com/2013/11/there-is-no-thread.html

    Even if the above link refers to C#, the model is pretty much equivalent in windows runtime, as it will be quite obvious from the diagrams shown there (it relays on OS support).

    This link bellow shows you how to consume async APIs more easily in C++/CX, similar to how it is done in C#

    http://blogs.msdn.com/b/vcblog/archive/2014/11/12/resumable-functions-in-c.aspx



    Wednesday, September 9, 2015 1:21 PM

All replies

  • You should be able to add an await

    something like

    auto myreturnedvalue = __await dBox->ShowAsync();

    Wednesday, September 2, 2015 8:14 PM
  • I already tried that.  Doesn't work.  I get the following error: this await expression requires a suitable "await_ready" function and none was found
    Thursday, September 3, 2015 5:57 AM
  • try this...

    #include <ppltasks.h>

    using namespace concurency;

    ...

    auto taskToAwait = whatever->ShowAsync();

    auto taskAwaiter = create_task(taskToAwait);

    taskAwaiter.get()

    Thursday, September 3, 2015 6:30 AM
  • Hi Quantum Maelstorm,

    I would suggest you reading this document: Asynchronous programming in C++

    You can chain your task together, for example:

    void ContentDialogUWPCPP1::MainPage::Button_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
    {
     ContentDialog^ dBox =
      ref new ContentDialog();
     dBox->PrimaryButtonText = "OK";
     dBox->SecondaryButtonText = "Cancel";
     dBox->Content = "Please confirm the message";
     dBox->Title = "Content Dialog";
     auto task = create_task(dBox->ShowAsync());
    
     task.then(
      [](ContentDialogResult result)
     {
      // the user has dismissed the dialog, do something else. 
     }
     );
    
    }


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Thursday, September 3, 2015 7:07 AM
    Moderator
  • <rant>You know, the way Microsoft implemented this is annoying to say the least.  Right now, I am half tempted to code in a mutex lock to force synchronization.  This 'lamba" BS is very limiting.  Now I do understand multithreading and concurrency as I have written network server software as well as kernel level code in Unix using the pthreads library.  But Microsoft's implementation makes no sense to me.</rant>

    So, how do you get the data out of the lamba?  Everything that I've tried either won't compile saying that it will not accept local variables, or it runs async instead of sync.  I'm about ready to start pulling my hair out (what little I have left).

    Thursday, September 3, 2015 4:37 PM
  • If this is the first time running around with UI programming, I can understand your frustration.

    But showing dialog boxes the "sync" way is dirty and causes a lot of issues with the control that shows that dialog, because it essentially blocks the message loops, which will cause the OS to believe the application is not responding and terminate it.

    http://stackoverflow.com/questions/361493/why-are-modal-dialog-boxes-evil

    You can use global variables to get out stuff of the lambdas.

    Please note that showing the dialog box is not really multithreaded. the UI thread will be the one processing the dialog box's message loop, but it will do so asynchronously with the main message loop, meaning neither will be blocked.

    Friday, September 4, 2015 6:42 AM
  • I have done some UI programming before on windows, but that was using Win32 and under Windows XP.  I haven't done much with it though.  From what I gather, the main loop is what collects and responds to events.  When the user clicks on a button, it generates an event.  The dispatcher correlates the event with a handler and forks off a thread to handle that event.  Before multithreading, we would stop all message processing to handle the event.  Now we just spawn new threads to handle the event.  At least in my server codes, once I complete the setup, and depending on the situation, I will either put events into a queue to be worked by worker threads or when an event comes in (network connection, control connection, control command, etc...) just spawn a new thread using pthread_create.

    So, is this what Windows is now doing behind the scenes?  Because right now, I do not see any indication of the main loop anywhere in the code.  But then again, I figure that the main loop is blocked in the kernel waiting for an event to be sent to it via the UI.

    Friday, September 4, 2015 3:35 PM
  • The model is slightly different come .net 4.5 (and winRT) and async/await.

    Instead of completely stopping the message loop, it continues to process messages that come from the OS, while still blocking user input and restricting it to the dialog that pops up. This allows applications to comply with the requirements of windows universal apps, which terminates applications that do not respond to OS messages for 10 seconds while still displaying dialog boxes.

    In fact, the whole point of async is to not block the message loop for extended periods of time.

    Whether showing that dialog is done by the UI thread or not is irrelevant. It will use synchronization contexts and from your point of view, the dialog is displayed by another thread, even if in essence it is not. This is why using a mutex does yield some results but not what you want to achieve.

    Another pitfall you should be aware of in async programming models is that something that is marked as async does not necessary create a new thread when it is called.

    http://blog.stephencleary.com/2013/11/there-is-no-thread.html

    Even if the above link refers to C#, the model is pretty much equivalent in windows runtime, as it will be quite obvious from the diagrams shown there (it relays on OS support).

    This link bellow shows you how to consume async APIs more easily in C++/CX, similar to how it is done in C#

    http://blogs.msdn.com/b/vcblog/archive/2014/11/12/resumable-functions-in-c.aspx



    Wednesday, September 9, 2015 1:21 PM