2012-10-12 22 views
1

我试图从三天后开始寻找对此的回答。这或者是我做了一些根本性的错误(有一个明显的错误),或者这个东西太新了,没有任何引用,我似乎无法弄清楚为什么这样的简单情况会失败。上下文“use_current”的任务继续不起作用

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

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

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 Store C++应用程序(例如Direct2D应用程序)中的任何位置,并且会失败(我将它放在“DirectXPage :: DirectXPage”构造函数体中,我期望它是主UI线程)。我做了一些可怕的错误吗?

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

回答

6

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

然而,持续不能运行,直到UI线程是免费的(即,它没有做任何工作的时候)。但是,在您的示例中,UI线程永远不会自由:构造函数DirectXPage正在UI线程上运行。构造函数DirectXPage将不会返回,直到延续执行并且继续不能执行,直到DirectXPage构造函数返回。

您需要允许构造函数返回,使UI线程可以自由地做其它工作(如执行的延续)。


还要注意的是,如果你使用的是fileLoaded跨线程通信,你需要使用一个std::atomic<bool>或其他一些适当的同步对象。简单的bool不足以进行同步。

+0

感谢詹姆斯,这听起来像是一个很好的解释(我很快将它标记为答案,因为我仍然有以下疑惑): 在我的脑海里,线程总是“活着”,因为它无法返回给创建它的调用者(否则该线程将被视为“终止”)。为了保持“活跃”,它需要处于长时间运行的循环中,或者等待同步对象(例如互斥体)。 ......(继续下) –

+0

如果上面的理解是真实的,那么“use_current”是这是令的另一个“构建”,只有在Windows Store应用UI线程(即UI线程必须有一些“差距使用“或”暂停“,允许”返回线程在其上下文中执行“)。而一个普通的“天真的大循环后台线程”没有这样的“构造”,因此“use_current”对他们来说是不可能的。这种理解是否正确? :) –

+0

正确:UI线程具有[消息队列](http://msdn.microsoft.com/en-us/library/windows/desktop/ms644927.aspx)。在传统的Windows(“桌面”)应用程序中,将会有一个循环来抽取消息并分发它们。在Windows应用商店应用中,此抽取发生在Windows运行时应用框架代码中。当您使用'use_current()'告诉PPL在UI线程上下文中继续时,当继续准备好运行时,会向UI线程发送一条消息。当UI线程输出这个消息时,它将被分派并且继续运行。 –