2015-05-28 2 views
0

Весь день я пытаюсь найти решение без каких-либо результатов. Ты единственная надежда.C++ Threads - Crashes

Я должен сделать звуковой синтезатор на основе библиотеки bass.h. Все работало нормально, пока я не хотел, чтобы он играл в отдельные потоки. Я решил сделать это на отдельные потоки:

void Synthezator::play(MonoStream *stream1, MonoStream *stream2) 
{ 
    threadParam data = {stream1, this}; 
    threadParam data2 = {stream2, this}; 
    int x = 6; 
    DWORD threadId; 
    DWORD threadId2; 
    //thread first (PlayThread, data); 
    //thread second (PlayThread, data2); 
    //first.join(); 
    //second.join(); 
    CreateThread(NULL, 0, PlayThread, (PVOID) &data, 0, &threadId); 
    CreateThread(NULL, 0, PlayThread, (PVOID) &data2, 0, &threadId2); 
    getchar(); 
} 

(комментируемые Ones работает таким же образом)

Аварии случайно встречается, (в случайные моменты времени, а не каждый раз) только тогда, когда два потока работают. Если я прокомментирую один из них - нет крушения.

функция PlayThread:

DWORD WINAPI Synthezator::PlayThread(PVOID data) 
{ 
    //cout << "kurwa"; 
    int i=0; 
    threadParam* dataNew = (threadParam*) data; 
    dataNew->stream->SeekBegin(); 
    while(!(dataNew->stream->eof())) 
    { 
     int no = 0; 
     note* a = dataNew->stream->Next(&no); 
     dataNew->pointer->PlayNote(a, no); 
     i++; 
    } 
} 

PlayNote:

void Synthezator::PlayNote(note* note, int count) 
{ 
    position = new double[count]; 
    generatorParams params = {synthType, count, note, position, this}; 
    HSTREAM SignalStream = BASS_StreamCreate (FREQUENCY, 1, 0, &Generator, &params); 
    if (SignalStream == 0) throw " Cannot create stream"; 

    if(note->sound != 0) { 
     if (!BASS_ChannelPlay (SignalStream, TRUE)) throw "Cannot play generated sample"; 
    } 
    const int secinusecs = 1000000; 
     sleep(secinusecs*floor(note->duration)/1000000); 
     usleep(secinusecs*(note->duration-floor(note->duration))); 
    if(note->sound != 0) { 
     BASS_ChannelStop(SignalStream); 
    } 
    BASS_StreamFree(SignalStream); 
    delete [] position; 
} 

Если я закомментировать эту строку, нет авария (но нет звука):

if (!BASS_ChannelPlay (SignalStream, TRUE)) throw "Cannot play generated sample"; 
+0

Судя по первому cout в PlayThread Вы некоторое время боролись с этим: D – AccessViolation

+0

Где объявляется переменная позиции? Он модифицирован из двух потоков одновременно! – AccessViolation

+0

Снятие линии «удалить [] позицию; решил проблему. Благодаря! – user1678401

ответ

0

Создание темы :

threadParam data = {stream1, this}; 
threadParam data2 = {stream2, this}; 
CreateThread(NULL, 0, PlayThread, (PVOID) &data, 0, &threadId); 
CreateThread(NULL, 0, PlayThread, (PVOID) &data2, 0, &threadId2); 

Внутри нити

dataNew->pointer->PlayNote(a, no); 

Проблема заключается в том, что вы используете одни и те же объекты функции PlayNote из двух разных местах. Таким образом, до того, как поток 1 завершит PlayNote, поток 2 входит в PlayNote. Первое, что в PlayNote - динамическое распределение памяти, хранящееся внутри объекта, так что поток 2 просто исказил указатель потока 1. В какой момент поведение нити 1 становится неопределенным, и гарантируется сбой, когда другой поток переключается обратно в contex после того, как первый поток завершит эту функцию и удалит указатель.

Добро пожаловать в многопоточное программирование. Вот твоя шляпа.

+0

Я не редактирую этот объект, поэтому я не понимаю, почему я не должен их использовать. Во всяком случае, удаление строки «delete [] position;» исправлена ​​проблема. – user1678401

+0

Вы редактируете объект в PlayNote при изменении позиции.И, удалив удаление, вы ввели утечку памяти и вызовите детерминированное поведение, если в противном случае произошел сбой. Сделать положение локальным для PlayNote, оставив в удалении, является лучшим решением. – Aumnayan

0

Если position член является единственным членом Вы изменяете в разных потоках, то я предлагаю Вам поставить обратно delete [] position; линию и объявить позицию приватной переменной: double* position = new double[count];

Таким образом, каждый поток будет иметь свой собственный набор позиций.

Хотя я должен видеть весь код, чтобы быть уверенным, что другие члены не изменяются несколькими потоками.