Asynchronous 带C+的UWP/WinRT+/CX:在异步任务链中,如何在它们之间传递数据?

Asynchronous 带C+的UWP/WinRT+/CX:在异步任务链中,如何在它们之间传递数据?,asynchronous,lambda,windows-runtime,c++-cx,uwp,Asynchronous,Lambda,Windows Runtime,C++ Cx,Uwp,我知道一个lambda的返回被输入到下一个lambda的参数中。但是,如果需要传递多个数据段,或者程序结构已经设置了一个lambda的返回类型,该怎么办 这是我的工作代码,其中两个都是打开文件选择器,然后以文本形式读取其内容,同时记住它来自于什么文件: create_task(picker->PickSingleFileAsync()) .then([this](StorageFile^ file) { if (file == nullptr) cancel_cu

我知道一个lambda的返回被输入到下一个lambda的参数中。但是,如果需要传递多个数据段,或者程序结构已经设置了一个lambda的返回类型,该怎么办

这是我的工作代码,其中两个都是打开文件选择器,然后以文本形式读取其内容,同时记住它来自于什么文件:

create_task(picker->PickSingleFileAsync())
.then([this](StorageFile^ file) 
    {
        if (file == nullptr) cancel_current_task();
        m_OpenFilename = file->Name;
        return FileIO::ReadTextAsync(file);
    })
.then([this](String^ fileContents)
    {
        //do something with the filename and file contents
    });
请注意,为了实现这一点,我需要添加一个类变量来存储异步任务之间的文件名。这让我觉得很糟糕,原因有很多:

  • 有一个类变量供单个方法内部使用是很难看的
  • 这个线程安全吗?如果有人疯狂地打开文件选择器并选择文件,那么这些异步任务在访问m_OpenFilename时是否会相互碰撞
  • 这只是一个带有一个变量的简单示例,但假设我还希望跟踪文件的路径、文件属性以及其他一些特性。现在,随着类变量数量的增加,类看起来越来越丑陋
我的第一种方法是在函数的作用域中设置一个局部变量,并通过将捕获列表更改为
[这是OpenFilename]
将其传递到每个lambda函数中。但是,这将失败,因为在执行lambda时,C++/CX的后台内存处理程序已经丢弃了
Openfilename
,从而在访问它时导致访问冲突


在我的示例中,如何将文件的元数据传递给
ReadTextAsync
的结果,以便我可以同时访问文件及其内容?

最简单的方法是继续构建嵌套的连续性链:

auto picker = ref new FileOpenPicker();
picker->FileTypeFilter->Append(L".txt");
picker->SuggestedStartLocation = PickerLocationId::Desktop;
auto task = create_task(picker->PickSingleFileAsync()).then(
  [](StorageFile^ file)
{
  auto name = file->Name;
  auto task = create_task(file->OpenReadAsync()).then(
    [name](IRandomAccessStreamWithContentType^ iras)
  {
    OutputDebugString(name->Data());
  });
});
如果您不想这样做(无论出于何种原因),另一种选择是使用
共享\u ptr
保存该值;在本例中,我将保留助手
文件\u info
类型中的名称和创建日期:

struct file_info
{
  Platform::String^ name;
  Windows::Foundation::DateTime created;
};

auto picker = ref new FileOpenPicker();
picker->FileTypeFilter->Append(L".txt");
picker->SuggestedStartLocation = PickerLocationId::Desktop;
auto info = std::make_shared<file_info>();

auto task = create_task(picker->PickSingleFileAsync()).then(
  [info](StorageFile^ file) 
{
  info->name = file->Name;
  info->created = file->DateCreated;
  return create_task(file->OpenReadAsync());
}).then(
  [info](IRandomAccessStreamWithContentType^ iras)
  {
    OutputDebugString(info->name->Data());
    OutputDebugString(L"\n");
    wchar_t datetime[100];
    _i64tow_s(info->created.UniversalTime, datetime, 100, 10);
    OutputDebugString(datetime);
});
结构文件信息 { 平台::字符串^name; 创建了Windows::Foundation::DateTime; }; 自动选取器=ref new FileOpenPicker(); 选择器->文件类型过滤器->附加(L“.txt”); picker->SuggestedStartLocation=PickerLocationId::Desktop; 自动信息=标准::使_共享(); 自动任务=创建任务(picker->PickSingleFileAsync()),然后( [信息](存储文件^file) { 信息->名称=文件->名称; 信息->已创建=文件->已创建日期; 返回创建任务(文件->OpenReadAsync()); }).那么( [信息](irandomaccesstreamwithcontenttype^iras) { OutputDebugString(信息->名称->数据()); OutputDebugString(L“\n”); wchar_t datetime[100]; _i64tow_s(信息->创建的.UniversalTime,日期时间,100,10); OutputDebugString(日期时间); });