You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何关闭进度条对话框时触发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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:10:55