CRITICAL_SECTION在使用DuplicateOutput时发生死锁

CRITICAL_SECTION occurs deadlock when using DuplicateOutput

本文关键字:死锁 DuplicateOutput SECTION CRITICAL      更新时间:2023-10-16

我正在用IDXGIOutputDuplication编写c++/CLI程序。

我想从多个线程获取图像,所以我使用了CriticalSection。但是,包含"AcquireNextFrame()"answers"ReleaseFrame()"的代码,线程被死锁。

如果UpdateDesktopImage()从程序中删除,则不会发生死锁。这些函数调用来自。net框架线程(System.Threading.Thread)。我想知道原因和解决办法。

HRESULT DesktopDupli::Initialize(int dispno, IDXGIAdapter *adapter, IDXGIOutput *output)
{
    HRESULT hr = S_OK;
    IDXGIOutput1 *dxgi_op1 = NULL;
    DXGI_OUTPUT_DESC desc_op;
    hr = output->GetDesc(&desc_op);
    sw = desc_op.DesktopCoordinates.right - desc_op.DesktopCoordinates.left;
    sh = desc_op.DesktopCoordinates.bottom - desc_op.DesktopCoordinates.top;
    D3D_FEATURE_LEVEL FeatureLevels[] =
    {
        D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL_10_1,
        D3D_FEATURE_LEVEL_10_0,
        D3D_FEATURE_LEVEL_9_1
    };
    D3D_FEATURE_LEVEL level;
    UINT levels = ARRAYSIZE(FeatureLevels);
    hr = D3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN,
        NULL, 0, FeatureLevels, levels,
        D3D11_SDK_VERSION, &device, &level, &context);
    if (FAILED(hr)) goto EXIT;
    hr = output->QueryInterface(__uuidof(IDXGIOutput1), (void**)&dxgi_op1);
    if (FAILED(hr)) goto EXIT;
    hr = dxgi_op1->DuplicateOutput(device, &dupli);
    if (FAILED(hr)) goto EXIT;
    this->dispno = dispno;
    pixelbufLen = sh * sw * 4;
    pixelbuf1 = new BYTE[pixelbufLen];
EXIT:
    RELEASE(dxgi_op1);
    return hr;
}
void DesktopDupli::Remove()
{
    EnterCriticalSection(&csec);
    // delete some buffer
    if (pixelbuf){
        delete[]pixelbuf;
        pixelbuf = NULL;
    }
    LeaveCriticalSection(&csec);
}
HRESULT DesktopDupli::UpdateDesktopImage()
{
    EnterCriticalSection(&csec);
    HRESULT hr = S_OK;
    IDXGIResource* res = NULL;
    ID3D11Texture2D *deskimage = NULL;
    DWORD c = GetTickCount();
    if (c >= lastUpdate && c < lastUpdate + 10) goto EXIT;
    lastUpdate = c;
    if (!dupli/*<-IDXGIOutputDuplication */) {
        hr = E_POINTER;
        goto EXIT;
    }
    dupli->ReleaseFrame();
    if (FAILED(hr)) goto EXIT;
    hr = dupli->AcquireNextFrame(500, &frameinfo, &res);
    if (hr == DXGI_ERROR_WAIT_TIMEOUT) {
        hr = S_OK;
        goto EXIT;
    } else if (FAILED(hr)){
        goto EXIT;
    }
    hr = res->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&deskimage);
    if (FAILED(hr)) goto EXIT;
    if (frameinfo.AccumulatedFrames == 0) {
        dupli->ReleaseFrame();
    }else {
        hr = SetPixel(deskimage); //CopySubresourceRegion
    }
EXIT:
    RELEASE(deskimage);
    RELEASE(res);
    LeaveCriticalSection(&csec);
    return hr;
}

in:

hr = res->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&deskimage);
    if (FAILED(hr)) goto EXIT;

您忘记在EXIT之前添加dupli->ReleaseFrame()