How to wait for an IAsyncAction?

后端 未结 4 2136
深忆病人
深忆病人 2021-01-04 09:06

In Windows Store Apps, C++(C# is similar though), doing something like

IAsyncAction^ Action = CurrentAppSimulator::ReloadSimulatorAsync(proxyFile);
create_ta         


        
4条回答
  •  失恋的感觉
    2021-01-04 09:26

    In general you should use the continuations (.then(...)), like Adam's answer says, and not block. But lets say you want to do a wait for some reason (for testing some code?), you can trigger an event from the last continuation (to use C# parlance):

        TEST_METHOD(AsyncOnThreadPoolUsingEvent)
        {
    
            std::shared_ptr _completed = std::make_shared();
    
    
            int i;
    
            auto workItem = ref new WorkItemHandler(
                [_completed, &i](Windows::Foundation::IAsyncAction^ workItem)
            {
    
                Windows::Storage::StorageFolder^ _picturesLibrary = Windows::Storage::KnownFolders::PicturesLibrary;
    
                Concurrency::task _getFileObjectTask(_picturesLibrary->GetFileAsync(L"art.bmp"));
    
                auto _task2 = _getFileObjectTask.then([_completed, &i](Windows::Storage::StorageFile^ file)
                {
    
                    i = 90210;
    
                    _completed->set();
    
                });
    
            });
    
            auto asyncAction = ThreadPool::RunAsync(workItem);
    
            _completed->wait();
    
    
            int j = i;
    
        }
    

    By the way, for some reason this method causes an exception when after it is over in visual studio tests. I've tested it in an app too though and it worked with no problem. I'm not quite sure what the problem is with the test.

    If anybody wants a C++/Wrl example then I have that too.

    Update 07/08/2017: As requested here is a C++/Wrl example. I have just run this in a Universal Windows (10) Test project in Visual Studio 2017. The key thing here is the weird part Callback, IWorkItemHandler , FtmBase >> , as opposed to just Callback . When I had the latter, the program jammmed except for when it was in a .exe project. I found this solution here: https://social.msdn.microsoft.com/Forums/windowsapps/en-US/ef6f84f6-ad4d-44f0-a107-3922d56662e6/thread-pool-task-blocking-ui-thread . See "agile objects" for more information.

    #include "pch.h"
    #include "CppUnitTest.h"
    #include 
    #include 
    #include 
    #include 
    #include 
    #include "concrt.h"
    #include 
    
    
    using namespace Microsoft::VisualStudio::CppUnitTestFramework;
    using namespace ABI::Windows::Foundation;
    using namespace Microsoft::WRL;
    using namespace Microsoft::WRL::Wrappers;
    using namespace Windows::System::Threading;
    
    using namespace ABI::Windows::Foundation;
    using namespace ABI::Windows::System::Threading;
    
    
    
    namespace TestWinRtAsync10
    {
        TEST_CLASS(UnitTest1)
        {
        public:
    
            TEST_METHOD(AsyncOnThreadPoolUsingEvent10Wrl)
            {
                HRESULT hr = BasicThreadpoolTestWithAgileCallback();
    
                Assert::AreEqual(hr, S_OK);
            }
    
            HRESULT BasicThreadpoolTestWithAgileCallback()
            {
    
                std::shared_ptr _completed = std::make_shared();
    
                ComPtr _threadPool;
                HRESULT hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_System_Threading_ThreadPool).Get(), &_threadPool);
    
                ComPtr asyncAction;
                hr = _threadPool->RunAsync(Callback, IWorkItemHandler, FtmBase>>([&_completed](IAsyncAction* asyncAction) -> HRESULT
                {
    
                    // Prints a message in debug run of this test
                    std::ostringstream ss;
                    ss << "Threadpool work item running.\n";
                    std::string _string = ss.str();
                    std::wstring stemp = std::wstring(_string.begin(), _string.end());
                    OutputDebugString(stemp.c_str());
                    // 
                    _completed->set();
    
                    return S_OK;
    
                }).Get(), &asyncAction);
    
                _completed->wait();
    
                return S_OK;
            }
    
        };
    }
    

    Update 08/08/2017: More example, per the comments.

    #include "pch.h"
    #include "CppUnitTest.h"
    
    #include 
    #include 
    #include 
    #include 
    #include "concrt.h"
    #include 
    
    
    #include 
    
    using namespace ABI::Windows::Foundation;
    using namespace Microsoft::WRL;
    
    namespace TestWinRtAsync10
    {
        TEST_CLASS(TestWinRtAsync_WrlAsyncTesting)
        {
    
        public:
    
            TEST_METHOD(PackageClassTest)
            {
                ComPtr _pPackageStatics;
    
                HRESULT hr = GetActivationFactory(Microsoft::WRL::Wrappers::HStringReference(RuntimeClass_Windows_ApplicationModel_Package).Get(), &_pPackageStatics);
    
                ComPtr _pIPackage;
    
                hr = _pPackageStatics->get_Current(&_pIPackage);
    
                ComPtr _pIPackage3;
    
                hr = _pIPackage->QueryInterface(__uuidof(ABI::Windows::ApplicationModel::IPackage3), &_pIPackage3);
    
                ComPtr<__FIAsyncOperation_1___FIVectorView_1_Windows__CApplicationModel__CCore__CAppListEntry> _pAsyncOperation;
    
                hr = _pIPackage3->GetAppListEntriesAsync(&_pAsyncOperation);
    
                std::shared_ptr _completed = std::make_shared();
    
                _pAsyncOperation->put_Completed(Microsoft::WRL::Callback, ABI::Windows::Foundation::IAsyncOperationCompletedHandler <__FIVectorView_1_Windows__CApplicationModel__CCore__CAppListEntry*>, FtmBase >>
                    ([&_completed](ABI::Windows::Foundation::IAsyncOperation<__FIVectorView_1_Windows__CApplicationModel__CCore__CAppListEntry*>* pHandler, AsyncStatus status)
                {
                    __FIVectorView_1_Windows__CApplicationModel__CCore__CAppListEntry* _pResults = nullptr;
    
                    HRESULT hr = pHandler->GetResults(&_pResults);
    
                    ComPtr _pIAppListEntry;
    
                    unsigned int _actual;
    
                    hr = _pResults->GetMany(0, 1, &_pIAppListEntry, &_actual);
    
                    ComPtr _pDisplayInfo;
    
                    hr = _pIAppListEntry->get_DisplayInfo(&_pDisplayInfo);
    
                    Microsoft::WRL::Wrappers::HString _HStrDisplayName;
    
                    hr =  _pDisplayInfo->get_DisplayName(_HStrDisplayName.GetAddressOf());
    
    
                    const wchar_t * _pWchar_displayName = _HStrDisplayName.GetRawBuffer(&_actual);
    
    
                    OutputDebugString(_pWchar_displayName);
    
    
                    _completed->set();
    
                    return hr;
    
    
    
                }).Get());
    
                _completed->wait();
    
            };
    
        };
    }
    

    This outputted:

    TestWinRtAsync10

提交回复
热议问题