在_beginthread中接收到错误的数据

Receiving wrong data in _beginthread

本文关键字:错误 数据 beginthread      更新时间:2023-10-16

我想将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。

您使用线程函数的堆栈变量地址作为参数,这是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();
}

您正在传递一个指向"i"的指针,其中的值不断变化。当它启动第一个线程时,"i"可能已经发生了更改(从您的输出判断,到第二个线程创建时,它已经发生了变化),您的线程将不会产生您期望的输出。

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

另一种解决方案是欺骗编译器,不传递指针,而是传递"i"本身,该指针被强制转换为空指针。当然,在线程中,您不会取消引用它,而是简单地将它强制转换回int。

线程回调函数中需要一个互斥对象。

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();
}