2015-06-02 5 views
0

Я сделал кодировщик с использованием WIC. то я попытался использовать поток для наиболее трудоемкой части. которыйпотоки возвращают ошибки (иногда) в WIC

/*Encodes a bitmap source*/ 
hr = piBitmapFrame->WriteSource(
    piBitmapSrc, /*bitmap source*/ 
    rc    /*area which need to be wrote*/ 
    ); 

piBitmapSrc → WICBitmap

гс → WICRect, площадь прямоугольника, чтобы сделать работу

Это как я tryied.

HRESULT writeSrc(
    IWICBitmapFrameEncode *piBitmapFrame, 
    IWICBitmap *piBitmapSrc, 
    WICRect *rc 
    ) 
{ 
    /*Encodes a bitmap source*/ 
    hr = piBitmapFrame->WriteSource(
     piBitmapSrc, /*bitmap source*/ 
     rc    /*area which need to be wrote*/ 
     ); 

    return hr; 
} 

, а затем я его называю, как этот

const int numberOfThreads = 4; 
std::thread t[numberOfThreads]; 
int ht = (lHeight/numberOfThreads); 

WICRect rc; 
rc.X = 0; 
rc.Height = ht; 
rc.Width = lWidth; 

rc.Y = 0; 
t[0] = std::thread(writeSrc, piBitmapFrame, piBitmapSrc, &rc);  

rc.Y += ht; 
t[1] = std::thread(writeSrc, piBitmapFrame, piBitmapSrc, &rc); 

rc.Y += ht; 
t[2] = std::thread(writeSrc, piBitmapFrame, piBitmapSrc, &rc); 

rc.Y += ht; 
rc.Height = (lHeight - (3*ht)); 
t[3] = std::thread(writeSrc, piBitmapFrame, piBitmapSrc, &rc); 

t[0].join(); 
t[1].join(); 
t[2].join(); 
t[3].join(); 

проблемы, piBitmapFrame->WriteSource() называют в 4 раза, но только 1 возвращает S_OK. другие 3 возвращает следующие коды ошибок

WINCODEC_ERR_STREAMWRITE

или

WINCODEC_ERR_CODECTOOMANYSCANLINES

почему это. и как я мог правильно использовать потоки для этого?

ответ

2

Возможно, вы захотите заглянуть в темы в целом больше. Темы разделяют глобальные данные и ресурсы. В вашем примере вы делитесь структурами piBitMapFrame и WICRect во всех четырех потоках.

Учитывая структуру WICRect, вы фактически изменяете данные внутри, когда вы отправляете потоки. Эти данные, после их изменения, будут видны всего работающих потоков. Все потоки ссылаются на один WICRect, который вы объявили, и если они дважды проверяют одну и ту же переменную - они могут найти другое.

Я не знаком с этой библиотекой, но вы должны проверить, является ли WriteSource потокобезопасным вызовом. Имеет ли piBitmapFrame данные, которые могут быть изменены вызовом WriteSource? Вспомните пример WICRect выше, WriteSource, вероятно, не будет обрабатывать внутренние данные, изменяющие средние вызовы.

Пример:

Эта программа пытается напечатать на стандартный вывод в двух потоков исполнения, без какой-либо синхронизации относительно того, кто пишет, когда. Это не приведет к сбою, cout будет потокобезопасным, но он не даст результата, который вы ожидаете. Результатом будет оба символа чередования потоков в буфере stdout.

#include <iostream> 
#include <thread> 

void say_hello(){ 

    /* no locking to prevent stdout contention */ 
    for (int i = 0; i < 10; i++){ 
     std::cout << "Hello from thread " << std::this_thread::get_id() << "!!!" << std::endl; 
    } 
} 

int main(){ 

    int i; 
    // create our thread 
    std::thread ct1(say_hello); 

    // say hello ourselves 
    say_hello(); 

    // wait for thread ct1 to finish execution. 
    ct1.join(); 
    return i; 
} 

Результат:

HHeelllloo ffrroomm tthhrreeaadd 00xx170fcf5fd78b000007!3!0!0 
!!H!e 
llHoe lflroo mf rtohmr etahdr e0axd1 00cx57df8f0f070b!0!0!7 
30H0e!l!l!o 
fHreolml ot hfrreoamd t0hxr1e0acd5 d08x070f0f!f!7!b 
00H7e3l0l0o! !f!r 
omH etlhlroe afdr o0mx 1t0hcr5eda8d0 000x!7!f!f 
f7Hbe0l0l7o3 0f0r!o!m! 
thHreelaldo 0fxr1o0mc 5tdh8r0e0a0d! !0!x 
7fHfefl7lbo0 0f7r3o0m0 !t!h!r 
eaHde l0lxo1 0fcr5odm8 0t0h0r!e!a!d 
0Hxe7lflfof 7fbr0o0m7 3t0h0r!e!a!d 
0Hxe1l0lco5 df8r0o0m0 !t!h!r 
eaHde l0lxo7 fffrfo7mb 0t0h7r3e0a0d! !0!x 
10Hce5ldl8o0 0f0r!o!m! 
thHreelaldo 0fxr7ofmf ft7hbr0e0a7d3 000x!1!0!c 
5dH8e0l0l0o! !f!r 
omH etlhlroe afdr o0mx 7tfhfrfe7abd0 007x31000c!5!d!8 
00H0e!l!l!o 
from thread 0x7fff7b007300!!!