zoukankan      html  css  js  c++  java
  • IAsyncAction和IAsyncOperation接口

    Windows 8 Store编程中常见的两个异步接口IAsyncActionIAsyncOperation都是从IAsyncInfo继承,分别用于没有返回值和有返回值的场合,还分别提供了带有进度的版本IAsyncActionWithProgressIAsyncOperationWithProgress开始我以为concurrency::create_task是一个类似于CreateThread一样的函数,后来MessageDialog::ShowAsync()让我意识到线程应该是创建于Async方法中,于是写个简单的Project测试一下,以增强了解。

    新建一个空白XAML工程,在MainPage.xaml中添加一个按钮,Click处理函数中加上如下代码:

    //openOperation是MainPage类的一个Windows::Foundation::IAsyncOperation<Windows::Storage::StorageFile^>^类型成员变量,初始化为nullptr
    if(openOperation == nullptr)
    {
      Windows::Storage::Pickers::FileOpenPicker^ openPicker = ref new Windows::Storage::Pickers::FileOpenPicker();
      openPicker->ViewMode = Windows::Storage::Pickers::PickerViewMode::Thumbnail;
      openPicker->SuggestedStartLocation = Windows::Storage::Pickers::PickerLocationId::PicturesLibrary;
      openPicker->FileTypeFilter->Append(".png");
      openOperation = openPicker->PickSingleFileAsync();
    }
    else
    {
      openOperation->Completed = ref new Windows::Foundation::AsyncOperationCompletedHandler<Windows::Storage::StorageFile^>([this](Windows::Foundation::IAsyncOperation<Windows::Storage::StorageFile^>^ asyncInfo, Windows::Foundation::AsyncStatus asyncStatus)
      {
        if(asyncStatus == Windows::Foundation::AsyncStatus::Completed)
        {
          Windows::Storage::StorageFile^ file = asyncInfo->GetResults();
          Windows::UI::Core::DispatchedHandler^ handler = ref new Windows::UI::Core::DispatchedHandler([this, file]()
          {
            if(file != nullptr)
            {
              this->Frame->Navigate(TypeName(ViewPage::typeid), safe_cast<Object^>(file));
            }
            else
            {
              Windows::UI::Popups::MessageDialog^ msgDlg = ref new Windows::UI::Popups::MessageDialog("Can't open this file.");
              msgDlg->ShowAsync();
            }
          });
          Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal, handler);
        }
      });
    }
    这里为什么要写一个如此别扭的逻辑,就是为了要测试一下IAsyncOperation接口的Completed属性,作为经常使用CreateThread函数的VC程序员,不知你是否会这样想,当调用Async类型的函数后,异步操作已经在另一个线程中启动了,这个时候我们再从当前线程里为Completed属性指定一个Handler,这样安全吗?就能确保当前线程不会在此处被中断?还是这里面另有别的玄机?所以我们就尽可能的滞后添加Handler,看看会有什么故事。

    新添加一个空白XAML页名为ViewPage.xaml,拖放一个Image控件,x:Name="imageShow",OnNavigatedTo函数中添加如下代码:

    Windows::Storage::StorageFile^ file = safe_cast<Windows::Storage::StorageFile^>(e->Parameter);
    if(file)
    {
      auto openOp = file->OpenAsync(Windows::Storage::FileAccessMode::Read);
      openOp->Completed = ref new Windows::Foundation::AsyncOperationCompletedHandler<Windows::Storage::Streams::IRandomAccessStream^>([this](Windows::Foundation::IAsyncOperation<Windows::Storage::Streams::IRandomAccessStream^>^ asyncInfo, Windows::Foundation::AsyncStatus asyncStatus)
      {
        if(asyncStatus == Windows::Foundation::AsyncStatus::Completed)
        {
          Windows::Storage::Streams::IRandomAccessStream^ stream = asyncInfo->GetResults();
          Windows::UI::Core::DispatchedHandler^ handler = ref new Windows::UI::Core::DispatchedHandler([this, stream]()
          {
            Windows::UI::Xaml::Media::Imaging::BitmapImage^ bmp = ref new Windows::UI::Xaml::Media::Imaging::BitmapImage;
            auto setOp = bmp->SetSourceAsync(stream);
            setOp->Completed = ref new Windows::Foundation::AsyncActionCompletedHandler([this, bmp](Windows::Foundation::IAsyncAction^ asyncInfo, Windows::Foundation::AsyncStatus asyncStatus)
            {
              if(asyncStatus == Windows::Foundation::AsyncStatus::Completed)
              {
                Windows::UI::Core::DispatchedHandler^ handler = ref new Windows::UI::Core::DispatchedHandler([this, bmp]()
                {
                  imageShow->Source = bmp;
                });
                Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal, handler);
              }
            });
          });
          Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal, handler);
        }
      });
    }

    不得不说,lambda表达式确实是个好东西。现在,编译你的Project,然后调试运行,在MainPage里,单击按钮,选择一张图片,然后程序再次显示MainPage,好像什么都没有做,然后你可以去喝杯水或者吃个苹果,等到你回来后,再次单击刚才那个按钮,一切正常的话,你会发现程序导航到了ViewPage并且显示了刚才你选择的那张图片。

    经多次测试发现,无论多久之后再添加Completed Handler,程序都可以顺利执行,而且值得注意的是只可以添加一次,再次改动就会造成异常。

    看看代码,你会怎么想?事到如今,不妨想当然一下,Async线程中是不是存在一个类似于事件对象的东西,初始是Reset状态,当线程完成工作后就等待在此处,当你改动Completed属性时,set方法调用了SetEvent函数(这或许就是Completed是一个property而非一个event的原因?),然后Async线程得以继续到你指定的Handler中去执行,这时已是时过境迁,再次改动Completed属性当然不合理,所以要抛出异常。

    没有找到官方说明,完全属于推测,或有疏漏之处,望不吝指正。

  • 相关阅读:
    病毒写法,资源的释放.
    MinHook库的使用 64位下,过滤LoadLibraryExW
    系统权限远程线程注入到Explorer.exe
    【Unity】4.5 树木创建器
    【Unity】4.4 添加角色控制器
    【Unity】4.3 地形编辑器
    【Unity】4.2 提升开发效率的捷径--导入 Unity 5.3.4 自带的资源包
    【Unity】4.1 创建组件
    【Unity】4.0 第4章 创建基本的游戏场景
    【Unity】3.6 导入图片资源
  • 原文地址:https://www.cnblogs.com/youlin/p/2805199.html
Copyright © 2011-2022 走看看