树莓派Mono环境下System.IO.File.Copy阻塞应用问题求助
解决树莓派Mono环境下FAT/FAT32 U盘File.Copy阻塞应用的问题
问题根源推测
Mono对FAT/FAT32文件系统的File.Copy实现可能依赖了底层同步IO操作,且未做线程隔离优化——即便在独立线程中执行,也会因为文件系统全局锁或Mono的IO线程池限制,阻塞整个应用进程。而exFAT/NTFS的Linux驱动本身支持更完善的异步IO,独立进程则因资源隔离,不会影响主应用。
可行解决办法
手动实现异步分块复制
放弃使用System.IO.File.Copy,改用FileStream的异步方法分块读写,绕过Mono原生同步实现的瓶颈。示例代码:public async Task CopyFileAsync(string sourcePath, string destPath) { using var sourceStream = new FileStream(sourcePath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.Asynchronous); using var destStream = new FileStream(destPath, FileMode.Create, FileAccess.Write, FileShare.None, 4096, FileOptions.Asynchronous); await sourceStream.CopyToAsync(destStream, 4096); }这种方式通过真正的异步IO避免阻塞主线程或进程。
切换到.NET 6+替代Mono
树莓派已支持官方.NET SDK,.NET对Linux文件系统的IO处理比Mono更现代、优化更充分,大概率能解决FAT/FAT32下的阻塞问题。只需将项目迁移到.NET,重新编译部署即可。修改U盘挂载参数
编辑/etc/fstab,给FAT/FAT32的挂载项添加async参数,让文件系统操作以异步方式执行。比如原挂载行:/dev/sda1 /mnt/usb vfat defaults 0 0修改为:
/dev/sda1 /mnt/usb vfat defaults,async 0 0修改后执行
sudo mount -a重新挂载,可让底层IO操作不再阻塞进程。用独立进程执行复制
既然独立应用运行无阻塞问题,可把复制逻辑封装成单独的控制台程序,主应用通过Process.Start启动该程序执行复制;也可直接调用系统cp命令:var process = new ProcessStartInfo { FileName = "cp", Arguments = $"{sourcePath} {destPath}", UseShellExecute = false, CreateNoWindow = true }; Process.Start(process);借助进程间的资源隔离避免主应用被阻塞。
内容的提问来源于stack exchange,提问作者hunterjm
相关产品推荐
相关产品推荐

