在下面的代码中,CreateFileAsync()
的延续既不打印也不访问pdone
。但是,会创建零长度文件Hello.txt。
auto pdone = make_shared<bool>(false);
create_task(folderLocal->CreateFileAsync("Hello.txt", CreationCollisionOption::ReplaceExisting)).then([pdone](StorageFile ^file) {
OutputDebugString(L"In CreateFileAsync continuation!\n");
*pdone = true;
});
create_task([pdone]{
OutputDebugString(L"In my task!\n");
});
create_async([pdone]{
OutputDebugString(L"In my async!\n");
});
while (!*pdone) {}
OutputDebugString(L"Done!\n");
在调试器中:
In my task!
In my async!
我对调试WinRT线程还不是很熟悉,但我没有看到任何明显的异常或任何原因不能执行异步操作的继续。目标平台是Hololens模拟器。
任何想法都表示赞赏。 谢谢!
答案 0 :(得分:1)
上面的Harry评论很可能是罪魁祸首 - 如果你在UI线程上发起这个,那么默认情况下,C ++任务库(PPL)将尝试在同一个线程上安排完成。如果您正在旋转等待完成的线程(经典死锁),这将永远不会发生。
如果你必须这样做(虽然你真的应该试着避免它),你需要使用&#34;继续上下文&#34;告诉PPL在其他地方运行延续。
这是一个例子。首先,基本的XAML(只是粘贴在空白C ++ XAML项目的Grid
内):
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<Button Content="Hang the UI thread" Click="Hang"/>
<Button Content="Do not do this" Click="DoNotDoThis"/>
</StackPanel>
代码(只需在MainPage
构造函数后粘贴):
using namespace Windows::Storage;
using namespace concurrency;
void DoIt(task_continuation_context& context)
{
auto folder = ApplicationData::Current->LocalFolder;
auto done = std::make_shared<bool>(false);
create_task(folder->CreateFileAsync(L"x", CreationCollisionOption::ReplaceExisting))
.then([done](StorageFile^ file) mutable
{
OutputDebugString(L"Done creating file\n");
*done = true;
}, context);
OutputDebugString(L"Going to wait... DO NOT DO THIS IN PRODUCTION CODE!\n");
while (!*done)
;
OutputDebugString(L"Done waiting\n");
}
void MainPage::Hang(Platform::Object^ sender, RoutedEventArgs^ e)
{
OutputDebugString(L"Starting Hang\n");
// The default context == the UI thread (if called from UI)
DoIt(task_continuation_context::use_default());
OutputDebugString(L"Ending Hang\n");
}
void MainPage::DoNotDoThis(Platform::Object^ sender, RoutedEventArgs^ e)
{
OutputDebugString(L"Starting DoNotDoThis\n");
// An arbitrary context will pick another thread (not the UI)
DoIt(task_continuation_context::use_arbitrary());
OutputDebugString(L"Ending DoNotDoThis\n");
}
如上所述,你不应该这样做。如果您需要同步文件I / O,并且您正在访问自己包中的文件,请使用Win32 API CreateFile2
。如果您需要访问包之外的文件(例如,从文件选择器或照片库),您应该使用完全异步编程方法。
答案 1 :(得分:0)
我相信使用task_continuation_context :: use_arbitarty()是这样做的正确方法,但我认为微软建议使用它略有不同,除非我误解了这个链接(一直滚动到底部):https://msdn.microsoft.com/en-us/library/hh750082.aspx
create_task(folderLocal->CreateFileAsync("Hello.txt", CreationCollisionOption::ReplaceExisting)).then([pdone](StorageFile ^file) {
OutputDebugString(L"In CreateFileAsync continuation!\n");
*pdone = true;
}, task_continuation_context::use_arbitrary());