在_beginthread中接收错误的数据

时间:2015-02-16 07:09:21

标签: c++ c multithreading

我想将int变量传递给线程。

我的线程代码:

void record_WAVthread(void* data)
{
    int channelId = *(int*)data;
    cout<< "\n THREAD CREATED " << channelId;

    (...)

    _endthread();
}

我的线程创建代码:

extern HANDLE thread_audio_recording[MAX_INPUTS];
extern void record_WAVthread(void* data);

(...)  

case 's':
    if (!flag_recordingAudio) 
    {   
        //start recording
        audioRecManager.isRecording = flag_recordingAudio = true;
        for (int i = 0; i < 16; i++) 
        {
            thread_audio_recording[i] = (HANDLE)_beginthread(record_WAVthread, 0, &i);
        }
    }
    break;

输出:

 THREAD CREATED 0
 THREAD CREATED 5
 THREAD CREATED 5
 THREAD CREATED 9
 THREAD CREATED 14
 THREAD CREATED 15
 THREAD CREATED 12
 THREAD CREATED 11
 THREAD CREATED 9
 THREAD CREATED 12
 THREAD CREATED 8
 THREAD CREATED 7
 THREAD CREATED 4
 THREAD CREATED 2
 THREAD CREATED 3
 THREAD CREATED 6

我做错了什么?我应该得到1-16。

3 个答案:

答案 0 :(得分:2)

您正在使用堆栈变量的地址作为参数的线程函数,这是Windows多线程编程中的常见错误。

&i指向临时堆栈变量,该变量无法将其值保持在其范围之外。案件结束后可能是任何价值。您需要使用堆变量作为线程函数的参数。

但是对于您的代码,这里特别是一个简单的解决方案。

case 's':
    if (!flag_recordingAudio) 
    {   
        //start recording
        audioRecManager.isRecording = flag_recordingAudio = true;
        for (int i = 0; i < 16; i++) 
        {
            thread_audio_recording[i] = (HANDLE)_beginthread(record_WAVthread, 0, (void*)i);
        }
    }
    break;

void record_WAVthread(void* data)
{
    int channelId = (int)data;
    cout<< "\n THREAD CREATED " << channelId;

    (...)

    _endthread();
}

答案 1 :(得分:0)

您正在向“i”传递指针,其值不断变化。当它启动第一个线程时,'i'可能已经(并且,从你的输出判断,它已经通过第二个线程创建)改变了,你的线程将不会产生你期望的输出。

如果要正确执行此操作,请创建一个大小为16的int数组,用0,1,2,..填充它,并将指针传递给由'i'索引的数组元素(即&amp; arr [i ])

另一个解决方案是欺骗编译器而不传递指针,但传递'i'本身,转换为void指针。当然,在线程中你不会取消引用它,而只是将其强制转换为int。

答案 2 :(得分:0)

您需要在线程回调函数中使用互斥锁。

std::mutex g_mutex;
void record_WAVthread(void* data)
{
    g_mutex.lock();
    int channelId = *(int*)data;
    cout<< "\n THREAD CREATED " << channelId;
    g_mutex.unlock();
    (...)

    _endthread();
}