kennykerr / modern

Modern C++ for the Windows Runtime
https://moderncpp.com/
MIT License
295 stars 36 forks source link

async functions #12

Closed romka2411 closed 9 years ago

romka2411 commented 9 years ago

I tried create a chain based on your example:

Windows::Foundation::IAsyncOperation<StorageFile> a = picker.PickSingleFileAsync().Completed([](auto const & sender, AsyncStatus)
            {
                if (StorageFile file = sender.GetResults())
                {
                    MODERN_TRACE(L"%ls\n", file.Name().Buffer());
                }
                else
                {
                    MODERN_TRACE(L"Canceled\n");
                }
            });

there an error with casting variable 'a':Error C2440 'initializing': cannot convert from 'void' to 'Modern::Windows::Foundation::IAsyncOperationModern::Windows::Storage::StorageFile' App app.cpp 58

Also I tried await functions like advised on StackOverflow:

auto dicop = Windows::Devices::Enumeration::DeviceInformation::FindAllAsync();

            dicop.Completed([](auto dicopint, AsyncStatus) 
            {
                auto f = dicopint.GetResults();
                auto name = f.First().Current().Name();
                MessageDialog dialog(name, L"Hello World!");
                dialog.ShowAsync();
            });
            while (dicop.Status() == AsyncStatus::Started)
            {
                try
                {
                    auto mcw = Windows::UI::Core::CoreWindow::GetForCurrentThread();
                    mcw.Dispatcher().ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
                }
                catch (Exception& ex)
                {
                    auto a = ex.Result;
                }
            }

(placed like previous code in KeyUp function) the code under "try" throws E_UNEXPECTED. CoreWindow returned by "Windows::UI::Core::CoreWindow::GetForCurrentThread();" same as the "window.KeyUp([](CoreWindow const &cw, KeyEventArgs const & args)" (from KeyUp calling).

Am I wrong using this?

Also where exceptions from namespace Platform (like, AccessDeniedException, COMException etc)? Is there for now only one of them - base (Modern::Exception)?

kennykerr commented 9 years ago

The first example fails to compile with error C2440 because the Completed method does not return a value (hence void). Completed is a method on IAsyncOperation but you can just get a reference yourself as follows:

Windows::Foundation::IAsyncOperation<StorageFile> op = picker.PickSingleFileAsync();

op.Completed([](auto const & sender, AsyncStatus)
{
    // ...
});

The second example fails with E_UNEXPECTED because you're calling ProcessEvents and that method has already been called from IFrameworkView::Run (inside sdk.extend.h). You can't just call it whenever you like. If you want to tweak message processing then you must also override the Run method.

Yes, right now there is only Modern::Exception. You can check the HRESULT for specifics.

romka2411 commented 9 years ago
  1. So the only way get a last async action In chain - using std::future and await (Now)?
  2. In standard blank uap for win10 ProcessEvents doesn't call? Unfortunatly this is doesn't look like good method. In your CoreApp this code loops with throwing exceptions until status==Completed, in uap - "while" runs only one time. But, CPU usage in both situations the same. So I tried chains - they are runs faster.
kennykerr commented 9 years ago
  1. Well without the compiler's await support, you naturally need to handle your own stack ripping with callbacks by building your own state machine. I also have adapters for PPL tasks that provide a simpler alternative while sticking with ISO C++ but I haven't shipped those yet.
  2. I really don't understand what you're trying to do or achieve. ProcessEvents is called from your app's message loop inside IFrameworkView::Run. If you want to write a non-blocking message loop then that's where you need to do it.
romka2411 commented 9 years ago

(second question) just searched in google ways to wait windows runtime async function and found that.

As I understand, code under "try" must work same as task_ppl.wait().

Tried it in MainPage::OnNavigatedTo - it works. Tried it there - exceptions. It just an alternative to chains or await`s. I supposed that act inside CoreWindow class quite same like in MainPage.

kennykerr commented 9 years ago

I don’t know where you found that but its terrible advice. You should never poll completion with a loop. That’s just wasting CPU cycles. PPL’s task::wait blocks the calling thread until the task completes. If you want to run some code when the operation completes then stick the code inside the Completed lambda. That's what it’s for.