MAUI中MediaPicker PickPhotoAsync报错:无法访问已关闭的流
解决Android下MediaPicker/FilePicker流复制时的ObjectDisposedException问题
问题核心原因
在Android 11(API30)及以上版本中,MediaPicker或FilePicker返回的文件流会被系统自动回收,如果没有在流的生命周期内完成读取/复制操作,或者异步上下文处理不当,就会触发System.ObjectDisposedException。即使是官方示例代码,若在MVVM结构中没有正确处理异步流的生命周期,也会出现相同问题。
解决方案
1. 先将流缓存到内存再操作
避免直接使用Picker返回的原始流进行文件写入,先把流内容复制到MemoryStream中,再用内存流完成后续操作:
private async Task AddImageAsync() { // 先申请权限(必要步骤) var permissionStatus = await Permissions.RequestAsync<Permissions.Media>(); if (permissionStatus != PermissionStatus.Granted) { // 处理权限拒绝逻辑,比如提示用户 return; } var pickResult = await MediaPicker.Default.PickPhotoAsync(); if (pickResult == null) return; // 读取原始流到内存流,保留完整内容 using var sourceStream = await pickResult.OpenReadAsync(); using var memoryStream = new MemoryStream(); await sourceStream.CopyToAsync(memoryStream); memoryStream.Position = 0; // 重置流指针到起始位置 // 写入目标文件 var targetFilePath = Path.Combine(FileSystem.AppDataDirectory, $"{Guid.NewGuid()}.jpg"); using var fileStream = new FileStream(targetFilePath, FileMode.Create); await memoryStream.CopyToAsync(fileStream); // 更新ObservableCollection YourImageCollection.Add(new ADVImage { ImagePath = targetFilePath }); }
2. 使用异步命令确保上下文正确
确保你的AddImage命令是IAsyncRelayCommand(来自Microsoft.Toolkit.Mvvm),避免普通RelayCommand导致异步操作未被正确await:
// ViewModel中定义命令 public IAsyncRelayCommand AddImageCommand { get; } // 构造函数初始化 public ADVModel() { YourImageCollection = new ObservableCollection<ADVImage>(); AddImageCommand = new AsyncRelayCommand(AddImageAsync); }
3. 配置Android权限
在AndroidManifest.xml中添加必要权限:
<!-- API30-32需要的存储权限 --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> <!-- API33+需要的媒体权限 --> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
关键注意点
- 不要在原始流的
using块之外引用它,系统会在OpenReadAsync返回的流使用完毕后立即释放。 - 确保所有文件操作都在异步上下文中完成,避免同步阻塞导致流被提前回收。
内容的提问来源于stack exchange,提问作者Denis De Pauli
相关产品推荐
相关产品推荐

