IWICImagingFactory::CreateDecoderFromFilename() 即使在解码器被销毁后也会保持文件锁定

问题描述 投票:0回答:3

我仅使用

IWICImagingFactory::CreateDecoderFromFilename()
进行阅读。有没有办法可以传递类似
FILE_SHARE_READ
标志之类的东西?文件从上面的函数调用开始一直保持打开状态,直到程序终止。

在同一程序中的另一个操作期间,我尝试使用

CFile::Open()
,但收到错误 32(“该进程无法访问该文件,因为该文件正在被另一个进程使用”)。

c++ file share direct2d
3个回答
1
投票

我最终做的是使用

pImagePoolEntry->hFileHandle = CreateFile(
    path.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL,
    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

在致电

CreateDecoderFromFilename()
之前。

由于我已经在使用图像池来跟踪打开的共享图像,因此我只是添加了初始文件句柄并添加了当图像不再使用时使用的代码。

    


1
投票

CloseHandle()

 对文件做了什么,但它似乎在 
IWICBitmapDecoder 调用之后保持打开状态。它可能有一个错误,手柄没有关闭,谁知道呢。我找不到有关该行为的任何信息。事实上,除了这个问题之外,似乎没有人注意到(或者没有人关心)。

无论如何,正如托尼所暗示的,解决方案是手动打开文件并使用

Release()

 而不是 
CreateDecoderFromFileHandle()
。请注意,“文件句柄必须在解码器的生命周期内保持活动状态。”
所以这个:

CreateDecoderFromFilename()

变成这样:

void f(IWICImagingFactory* factory, const wchar_t* path) { IWICBitmapDecoder* decoder = nullptr; factory->CreateDecoderFromFilename( path, nullptr, GENERIC_READ, WICDecodeMetadataCacheOnLoad, &decoder); // ... decoder->Release(); }



0
投票

IWICFormatConverter 继承自 IWICBitmapSource。从这个意义上说,它

代表

IWICBitmapSource,如文档所述。当 WIC 从 (IWICBitmapDecoder*) 解码器的 (IWICBitmapFrameDecode*) 源创建 (IWICFormatConverter*) 转换器时,它不会立即复制 CreateDecoderFromFilename()/CreateDecoderFromFileHandle() 调用中使用的图像文件的像素数据。当程序中使用像素数据时,稍后执行转换器的数据处理(由 void f(IWICImagingFactory* factory, const wchar_t* path) { auto h = CreateFileW( path, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); IWICBitmapDecoder* decoder = nullptr; factory->CreateDecoderFromFileHandle( reinterpret_cast<ULONG_PTR>(h), nullptr, WICDecodeMetadataCacheOnLoad, &decoder); // ... decoder->Release(); CloseHandle(h); } 调用中使用的参数指定),并且该处理使用图像文件 I/O 缓冲区的数据。通过这种方式,管道避免了不必要的数据复制。

但是,当你解锁图像文件时,你会删除这个io缓冲区。因此,如果您想解锁文件并仍然保留图像像素数据,则必须复制此像素数据。例如,在 CloseHandle() 调用之前,使用调用 

converter->Initialize(...)

,您可以将转换器所指向的像素数据复制到内存。Detach() 结构,然后使用宽度/高度和创建 (IWICBitmapSource*) wicBitmap源图像的其他参数,包括复制到内存的像素数据:

converter.Detach()->CopyPixels(nullptr, stride, imagesize, pixels)
。图像文件的 io 缓冲区不拥有这个复制的像素数据,您可以安全地关闭文件句柄。
    

© www.soinside.com 2019 - 2024. All rights reserved.