为何关闭进度条对话框时触发read access violation错误?
文件加载时关闭进度对话框触发访问违例问题
问题描述
我尝试在读取并处理文件时显示进度条对话框,但关闭该对话框时代码抛出“read access violation”错误。具体错误信息为:__pUnknown 为 0xFFFFFFFFFFFFFFFF。以下是我的代码:
void LoadFile(StorageFile^ file) { ContentDialog^ loaderDialog = ref new ContentDialog(); loaderDialog->Title = L"Loading..."; loaderDialog->Content = ref new ProgressBar(); loaderDialog->ShowAsync(); Concurrency::create_task(FileIO::ReadTextAsync(file)) .then([&](Platform::String^ fileText) { // File processing parts are omitted. // ... loaderDialog->Hide(); // Read access violation! }); }
请问出现该错误的原因是什么?
问题原因分析
老哥,你这个问题其实是典型的异步回调中的悬空引用问题,具体拆解一下:
loaderDialog是LoadFile函数里的局部变量,当函数执行完毕后,这个对象就会离开作用域。由于是UWP的托管对象,垃圾回收器会很快标记它进行回收,底层的COM对象也会被释放。- 而
create_task启动的文件读取是异步操作,它的then回调会在后台任务完成后才执行。这时候LoadFile早就执行结束了,你通过[&]引用捕获的loaderDialog已经变成了指向已释放内存的无效指针,调用它的Hide()方法自然就触发了访问违例错误。
另外补充一点:loaderDialog->ShowAsync()本身也是异步方法,你直接调用后没有等待它完成,不过这不是触发当前错误的直接原因,但也是个需要留意的细节。
修复方案
最直接的解决办法是把lambda的捕获方式从引用捕获改成值捕获,这样会复制loaderDialog的引用计数,确保在回调执行时对象仍然存活:
void LoadFile(StorageFile^ file) { ContentDialog^ loaderDialog = ref new ContentDialog(); loaderDialog->Title = L"Loading..."; loaderDialog->Content = ref new ProgressBar(); loaderDialog->ShowAsync(); Concurrency::create_task(FileIO::ReadTextAsync(file)) .then([loaderDialog](Platform::String^ fileText) { // 替换为值捕获 // 文件处理逻辑 // ... loaderDialog->Hide(); }); }
你也可以选择把loaderDialog提升为类的成员变量,让它的生命周期和类实例绑定,避免函数执行完就被回收,不过值捕获的方式更简洁高效。
内容的提问来源于stack exchange,提问作者Jio Gim
相关产品推荐
相关产品推荐

