【问题标题】:Receiving wrong data in _beginthread在 _beginthread 中接收错误数据
【发布时间】:2015-02-16 07:09:21
【问题描述】:

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

【问题讨论】:

  • i 从 0 到 15。为什么要得到 1-16?另外,为什么将指向 i 的指针传递给 beginthread?为什么不直接通过 i 呢?
  • 真 0-15 我的错。

标签: c++ c multithreading


【解决方案1】:

你将堆栈变量的地址用作线程函数的参数,这是 Windows 多线程编程中的常见错误。

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

【讨论】:

  • 进行这些更改后,我得到了同样的错误。奇怪
  • @F1sher:值中应该没有错误。但是数字的顺序可以改变,因为线程0~15的执行顺序是不确定的。
  • 你是对的。我没有注意到。感谢您发布有效的编辑代码。
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

    你需要一个线程回调函数中的互斥锁。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-09-17
      • 1970-01-01
      • 2018-07-13
      • 2013-03-08
      • 1970-01-01
      • 2017-02-01
      • 2020-11-21
      • 1970-01-01
      相关资源
      最近更新 更多