【问题标题】:UWP/WinRT: How to perform a UI task upon completion of an asynchronous operation in a model?UWP/WinRT:如何在模型中完成异步操作后执行 UI 任务?
【发布时间】:2015-08-15 01:17:47
【问题描述】:

我遵循 MVVM 模式,并且有一个名为 DocumentStore 的模型。该类有一个方法如下:

void DocumentStore::Open_Document(StorageFile^ file) {
    create_task(FileIO::ReadTextAsync(file))
        .then([this, file](String^ fileContents)
    {
        // Take the fileContents and add them to internal data structure
    });
}

我的 ViewModel 正在弹出一个 FileOpenPicker 以获取一个文件,然后将其作为参数提供给 Open_Document

create_task(picker->PickSingleFileAsync())
    .then([this](StorageFile^ file) 
    {
        m_DocStore->Open_Document(file); 
        // Target location to do something
    }
);

我希望能够在 Open_Document 内部的任务完成后执行操作,即在处理完文件内容之后。

我的模型有没有办法通知任何感兴趣的听众任务已完成?

或者我的模型的Open_Document 方法本身应该是异步的吗?但是,我需要处理任务内部的数据结构,这不会导致我的方法在不同的线程上下文中运行吗?

我正在使用 C++/CX,但我会寻求任何帮助。

【问题讨论】:

  • 您是否考虑过将 lambda 传递给 OpenDocument,以便在异步工作完成时调用它?

标签: c++ asynchronous mvvm windows-runtime win-universal-app


【解决方案1】:

如果我理解正确,过程如下。

打开文件 -> 读取内容 -> 处理内容 -> 做其他事情。

您可以将异步操作推送到任务链,并使用 create_async 方法创建一个新的异步操作。

以下是供您参考的代码:

create_task(StorageFile::GetFileFromApplicationUriAsync(ref new Windows::Foundation::Uri("ms-appx:///Assets/XMLFile.xml")))
.then([](StorageFile^ file) {
    WriteLine("Read the file");
    return FileIO::ReadTextAsync(file);
}).then([](task<String^> task) {
    String ^ text = task.get();
    WriteLine("Content: " + text);
    return create_async([text]() {
        WriteLine("Process the text: " + text);
    });
}).then([](task<void> task) {
    task.get();

    WriteLine("Do STH else");
});

【讨论】:

  • 在我的情况下,读取文件和处理文本步骤发生在另一个类中,即模型。 ViewModel 会希望在文本处理完成后执行一项任务(例如,打开一个对话框,通知用户在文本中找到了什么)。我相信这类似于您当前的代码,即仅在“处理文本:”完成后才执行“Do STH else”。如果我没记错的话,在您当前的代码中,“Do STH else”可能发生在“Process the text:”之前,因为 return create_async 立即返回,对吧?
  • 不,“Do STH else”会在“处理文本”之后发生,我使用 task.get() 来确保它。
  • 啊,谢谢,没意识到。那么你有什么想法可以使它适合将模型与视图模型分开的代码吗?我使用 ViewModel 中的示例代码更新了问题,以使讨论更容易。 ViewModel 中的调用代码将无法访问任务对象来调用 task.get(),至少不能直接调用。我可以让模型中的 Open_Document 返回任务对象,尽管这让我觉得破坏了 MVVM 模型的精神。您认为,编写这种交互的正确方法是什么?
  • 次要代码 nit:您不需要在最后的延续中使用 task&lt;void&gt; 参数 - 接受任务的主要原因是您可以检测错误,但是由于您盲目地调用 get无论如何它都会抛出。因此,如果您确信不会传播任何异常,只需完全取消任务。
【解决方案2】:

我发布了我最终的结果,但我接受了 Jeffrey Chen 的回答,因为它帮助我到达那里。

我的模型现在有一个事件DocOpened。这是在完成Open_Document 时触发的。我使用一个能够在触发该事件时执行任务的处理程序为我的 ViewModel 订阅了该事件。

【讨论】:

    猜你喜欢
    • 2016-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多