IWICImagingFactory::CreateDecoderFromFilename() 即使在解码器被销毁后,也

IWICImagingFactory::CreateDecoderFromFilename() keeps the file locked even after the decoder is destroyed

本文关键字:解码器 CreateDecoderFromFilename IWICImagingFactory      更新时间:2023-10-16

我只用IWICImagingFactory::CreateDecoderFromFilename()阅读。有没有办法传递像FILE_SHARE_READ标志这样的东西?该文件从上面的函数调用中保持打开状态,直到程序终止。

在同一程序内的另一个操作中,我尝试使用CFile::Open(),但出现错误32("进程无法访问该文件,因为它正被另一个进程使用"(。

我最终做的是使用

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

在呼叫CreateDecoderFromFilename()之前。

由于我已经使用图像池来跟踪打开的共享图像,因此我只是添加了初始文件句柄,并添加了在图像不再使用时要使用的代码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();
}

变成这样:

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);
}