【发布时间】:2018-01-11 10:37:12
【问题描述】:
我在使用 Concurrency::task 从我的代码中列出一些设备时遇到问题:
去年在 Visual Studio 2015 中使用此代码:
Concurrency::create_task(Windows::Devices::Enumeration::DeviceInformation::FindAllAsync(Windows::Devices::Midi::MidiInPort::GetDeviceSelector()))
.then([](Windows::Devices::Enumeration::DeviceInformationCollection ^midiDeviceCollection) {
for (Windows::Devices::Enumeration::DeviceInformation^ portInformation : midiDeviceCollection){
//do stuff with device
}
});
但几个月后,...今天,我必须更新我的应用程序(同时我切换到 VS2017)。所以我重新打开并更新了项目,遗憾的是这段代码不再按应有的方式工作。在“then()”部分设置的断点永远不会到达,代码会继续执行而不会出错,就好像我的任务从未被调用过一样。
我想知道在执行 DeviceInformation::FindAllAsync 时是否有错误导致“then()”部分无法运行。在对任务(https://msdn.microsoft.com/fr-fr/library/dd492427.aspx)进行了一些研究之后,我找到了一种在任务运行时捕获异常的方法,因此我将代码转换为:
IAsyncOperation<DeviceInformationCollection^>^ deviceOp = DeviceInformation::FindAllAsync(MidiInPort::GetDeviceSelector());
Concurrency::task<DeviceInformationCollection^> deviceEnumTask = Concurrency::create_task(deviceOp);
deviceEnumTask.then([](Concurrency::task<DeviceInformationCollection^> t){
try{
DeviceInformationCollection ^midiDeviceCollection = t.get();
for (DeviceInformation^ portInformation : midiDeviceCollection) {
//do stuff with device
}
}catch (Platform::Exception^ e){
//do stuff with device
OutputDebugString(e->Message->Data());
}
});
同样的结果,应用永远不会进入“then()”,也不会抛出异常:-( .
所以我的问题是:这里有什么问题?这段代码是列出设备的最常用方法,我在其他网络上的几个地方都看到过它(而且它在我的案例中去年有效),所以我应该犯了一个错误或在其他地方遗漏了一些东西。
这是捕获任务错误的好方法吗?
更多信息:此代码直接在 MainPage 构造函数中调用,就在 InitializeComponent(); 之后.我正在运行 VS2017,目标平台最低版本是 10.0.10240.0,目标平台版本是 10.0.15063.0。该应用是在 x64 桌面计算机上构建和测试的。
非常感谢您的帮助。
编辑:
感谢 Sunteen Wu 和 David Pritchard(见下文),我能够找出问题的根源。正如答案中所述,上面的代码实际上是有效的,并且在调整大卫提出的错误处理后非常清晰和完整。在我的测试中,我的断点也放在了正确的线上。但实际上,不知不觉中,我在“//do stuff with device”中使用了一些更深层次的阻塞代码(此处不可见)。这阻止了 MainPage 构造函数,避免它继续执行直到调用的任务完成......显然任务仍然与主线程执行相关联,只要 MainPage 构造没有结束就不会运行,在我的情况下从未发生过 - >死锁!
【问题讨论】:
标签: exception concurrency uwp task c++-cx