1

自三天前以来,我一直在尝试寻找答案。要么我做了一些根本错误的事情(有一个明显的错误),要么事情太新而没有任何参考,我似乎无法理解为什么像这样的简单案例会失败。

下面的代码在一个Windows Store应用中使用了C++中的PPL任务库,模拟了一个文件加载操作,需要2秒才能跳出循环(当然这是为了用最少的代码说明问题,真正的循环做了其他渲染也显示进展)。

如果我使用“use_current”作为延续上下文,则代码的延续部分(即“fileLoaded = true”)永远不会被调用:

bool fileLoaded = false;
while (!fileLoaded)
{
    concurrency::task<void>([this]()
    {
        // Simulate file load delay
        concurrency::wait(2000);

    }).then([this, &fileLoaded]()
    {
        fileLoaded = true; // This never gets executed!

        // If the following is changed to "use_default" or 
        // "use_arbitrary", then this continuation gets called.
    }, concurrency::task_continuation_context::use_current());

    concurrency::wait(50);
}

如果我使用“use_default”或“use_arbitrary”,并且将“fileLoad”正确设置为“true”,则相同的代码可以工作。此代码可以放置在 Windows 应用商店 C++ 应用程序(例如 Direct2D 应用程序)中的任何位置,但它会失败(我已将其放置在“DirectXPage::DirectXPage”构造函数主体中,我希望它是主 UI 线程)。我做错了什么可怕的事情吗?

在此先感谢您的帮助!:)

4

1 回答 1

7

由于您.then()在 UI 线程上调用,因此use_current()将导致继续在 UI 线程上被安排执行。

However, that continuation cannot run until the UI thread is free (i.e., when it is not doing any work). But, in your example, the UI thread is never free: the DirectXPage constructor is running on the UI thread. The DirectXPage constructor will not return until the continuation executes and the continuation cannot execute until the DirectXPage constructor returns.

You need to allow the constructor to return so that the UI thread is free to do other work (like execute the continuation).


Also note that if you are using fileLoaded for cross-thread communication, you need to use an std::atomic<bool> or some other proper synchronization object. A simple bool is insufficient for synchronization.

于 2012-10-12T16:52:25.663 回答