使用DuplicateOutput时,CRITICAL_SECTION会发生死锁

时间:2015-10-17 05:46:13

标签: c++ multithreading winapi directx-11 critical-section

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

我想从多个线程获取图像,所以我使用了CriticalSection。但是,包含" AcquireNextFrame()"的代码和" ReleaseFrame()",线程陷入僵局。

如果从程序中删除了UpdateDesktopImage(),则不会发生死锁。这些函数从.NET Framework线程(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;
}

1 个答案:

答案 0 :(得分:0)

在:

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

您在dupli->ReleaseFrame()

之前忘了EXIT