FileStream.Dispose抛出UnauthorizedAccessException如何处理释放?

huangapple go评论82阅读模式
英文:

FileStream.Dispose throws UnauthorizedAccessException how to handle disposing?

问题

FileStream是从指向USB Printing Support驱动程序的SafeHandle创建的,因此它不是常规的FileStream

现在我正在尝试解决一个问题,当用户拔下并重新插入USB设备时。一个新的句柄被创建,而旧的句柄现在指向其他位置。我需要重新初始化连接,但在创建新连接之前,我的直觉是释放旧资源。

> 释放所有可释放的资源

当我尝试释放这个FileStream时,我得到了UnauthorizedAccessException,并显示常规消息访问路径被拒绝。我是否只需在Disconnect方法中将Dispose调用包装在try/catch块中,并将它们保持未释放状态?也许在USB I/O方面有比FileStream更好的方法?

以下是一些代码:

public void Connect()
{
    Disconnect();
    _printerHandle = UsbPrinterResolver.OpenUSBPrinter(ConnectionString);
    _printerStream = new FileStream(_printerHandle, FileAccess.ReadWrite);
}

protected void Disconnect()
{
    _printerStream?.Dispose(); // 仅在USB连接正常且有效时起作用
    _printerHandle?.Dispose();
    _printerStream = null;
    _printerHandle = null;
}

UsbPrinterResolver实际上是来自问题确定打印机名称对应哪个设备ID的解决方案,我只是修改了//FIXME部分。但是解析的句柄似乎工作得很好。

英文:

The FileStream is created from SafeHandle that points directly to USB Printing Support driver, so it is not a regular FileStream.

Now I am trying to fix a problem when a user unplugs and re-plugs the USB device. A new handle is created and the old one now points somewhere else. I need to reinitialize the connection, but before creating a new one my instinct is to Dispose the old resources

> Dispose everything that is disposable

Trying to dispose this FileStream I get UnauthorizedAccessException with regular message Access to the path is denied. Do I just wrap my Dispose calls in method Disconnect to try/catch and leave them undisposed as is? Maybe there is a better way for USB I/O than FileStream?

Here is some code:

public void Connect()
{
    Disconnect();
    _printerHandle = UsbPrinterResolver.OpenUSBPrinter(ConnectionString);
    _printerStream = new FileStream(_printerHandle, FileAccess.ReadWrite);
}
protected void Disconnect()
{
    _printerStream?.Dispose(); // only works when the usb connection is working and valid
    _printerHandle?.Dispose();
    _printerStream = null;
    _printerHandle = null;
}

The UsbPrinterResolver is actually the one from question Figuring which printer name corresponds to which device ID I just modified the //FIXME part. But the resolved handles seemed to work great.

答案1

得分: 1

FileStream在释放之前会在内部刷新流。

因此,你只需要在释放该对象的外部捕获异常。

至于释放句柄:无论如何,它都会被关闭,你不需要释放它,因为流“拥有”该句柄。请参见这里的源代码。所以你不需要保留它。

public void Connect()
{
    Disconnect();
    var printerHandle = UsbPrinterResolver.OpenUSBPrinter(ConnectionString);
    try
    {
        _printerStream = new FileStream(_printerHandle, FileAccess.ReadWrite);
    }
    catch
    {
        printerHandle.Dispose();  // 如果 FileStream 构造函数失败,需要释放句柄
        throw;
    }
}

protected void Disconnect()
{
    _printerStream?.Dispose();
    _printerStream = null;
}
英文:

FileStream internally flushes the stream before disposing.

So you just need to catch the exception on the outside of whatever is disposing this object.

As far as disposing the handle: it will be closed regardless, you don't need to dispose that because the stream "owns" the handle. See the source code here. So you don't need to keep it around.

public void Connect()
{
    Disconnect();
    var printerHandle = UsbPrinterResolver.OpenUSBPrinter(ConnectionString);
    try
    {
        _printerStream = new FileStream(_printerHandle, FileAccess.ReadWrite);
    }
    catch
    {
        printerHandle.Dispose();  // need to dispose the handle if FileStream ctor fails
        throw;
    }
}

protected void Disconnect()
{
    _printerStream?.Dispose();
    _printerStream = null;
}

huangapple
  • 本文由 发表于 2023年8月8日 22:03:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/76860318.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定