调用IMFSourceReader::ReadSample线程卡住,如何用TerminateThread终止?
调用IMFSourceReader::ReadSample时,遇到无法读取数据的情况,线程会卡住。尝试用TerminateThread()终止线程,但返回0(操作失败),错误码为6。另外尝试pthread_cancel时出现编译错误:
no suitable constructor exists to convert from "std::thread::native_handle_type" to "__ptw32_handle_t"
以下是示例代码:
#include <iostream> #include <vector> #include <codecvt> #include <string> #include <thread> #include <mutex> #include <chrono> #include <condition_variable> #include <Windows.h> using namespace std::chrono_literals; class MyObject { private: ... std::thread *t; std::mutex m; std::condition_variable cv; std::thread::native_handle_type handle; int getsample(uint8_t* data) { // call a ReadSample hr = pVideoReader->ReadSample( MF_SOURCE_READER_ANY_STREAM, // Stream index. 0, // Flags. &streamIndex, // Receives the actual stream index. &flags, // Receives status flags. &llTimeStamp, // Receives the time stamp. &pSample // Receives the sample or NULL. ); ... return 0; } int myfunc_wrapper(uint8_t* data) { int ret = 0; BOOL bpass = 0; if (t == nullptr) { t = new std::thread([this, &data, &ret]() { ret = this->getsample(data); this->cv.notify_one(); }); handle = t->native_handle(); t->detach(); } { std::unique_lock<std::mutex> l(this->m); if (this->cv.wait_for(l, 2500ms) == std::cv_status::timeout) { bpass = TerminateThread(handle, 0); if (bpass == 0) { std::cout << "TerminateThread Fail! " << GetLastError() << std::endl; } throw std::runtime_error("Timeout Fail 2500 ms"); } } delete t; t = nullptr; } public: int my_func(uint8_t* raw_data) { bool timedout = false; try { if (myfunc_wrapper(raw_data) != 0) return -1; } catch (std::runtime_error& e) { std::cout << e.what() << std::endl; timedout = true; } if (timedout) return -1; return 0; } }; int main() { uint8_t data[512]; MyObject* obj = new MyObject(); while (true) { obj->my_func(data); } return 0; }
程序输出:
TerminateThread Fail! 6 Timeout Fail 2500 ms TerminateThread Fail! 6 Timeout Fail 2500 ms ...
1. 分析TerminateThread失败原因
错误码6对应ERROR_INVALID_HANDLE,说明传入的线程句柄无效,问题出在:
- 调用
t->detach()后,std::thread对象不再管理线程,native_handle()返回的句柄可能已失效或被系统回收资源。 - detach后执行
delete t,直接销毁std::thread对象,但线程本身仍在运行,进一步导致句柄失效。
2. 优先采用优雅终止方案(不推荐暴力终止)
TerminateThread属于危险操作,可能引发内存泄漏、资源无法释放(如Media Foundation的COM对象)甚至进程崩溃,优先用以下原生机制:
方法一:改用IMFSourceReader异步读取模式
Media Foundation推荐异步读取样本,从根源避免线程阻塞,还能优雅终止:
- 调用
IMFSourceReader::SetCallback设置回调对象,实现IMFSourceReaderCallback接口。 - 需要终止时,调用
IMFSourceReader::CancelAllPendingReads取消所有未完成的读取请求,线程会自然退出。
方法二:同步读取模式下增加终止信号
在类中添加原子布尔变量std::atomic<bool> should_exit,在线程逻辑中检查该变量,同时用CancelAllPendingReads中断ReadSample的阻塞:
class MyObject { private: std::atomic<bool> should_exit = false; IMFSourceReader* pVideoReader = nullptr; // ...其他成员 int getsample(uint8_t* data) { while (!should_exit) { if (should_exit) break; HRESULT hr = pVideoReader->ReadSample( MF_SOURCE_READER_ANY_STREAM, 0, &streamIndex, &flags, &llTimeStamp, &pSample ); if (FAILED(hr)) break; // ...处理样本逻辑 } return 0; } int myfunc_wrapper(uint8_t* data) { int ret = 0; should_exit = false; std::thread t([this, data, &ret]() { ret = this->getsample(data); this->cv.notify_one(); }); { std::unique_lock<std::mutex> l(m); if (cv.wait_for(l, 2500ms) == std::cv_status::timeout) { if (pVideoReader) { pVideoReader->CancelAllPendingReads(); } should_exit = true; t.join(); throw std::runtime_error("Timeout Fail 2500 ms"); } } t.join(); return ret; } // ...其他代码 };
方法三:修正句柄问题(仅作为最后手段)
如果必须用TerminateThread,需保证句柄有效:
- 不要调用
t->detach(),保留std::thread对象直到线程终止。 - 用
DuplicateHandle复制线程句柄,避免原句柄被销毁:
// 创建线程后 HANDLE thread_handle = t->native_handle(); HANDLE dup_handle; DuplicateHandle(GetCurrentProcess(), thread_handle, GetCurrentProcess(), &dup_handle, 0, FALSE, DUPLICATE_SAME_ACCESS); // 使用dup_handle调用TerminateThread TerminateThread(dup_handle, 0); // 用完后关闭复制的句柄 CloseHandle(dup_handle);
注意:即使修正句柄,暴力终止仍可能引发资源泄漏,不建议使用。
3. 关于pthread_cancel的问题
Windows下std::thread的native_handle是Win32线程句柄,而pthread_cancel是POSIX线程库函数,两者不兼容,因此出现编译错误。Windows环境下应使用Win32线程API,不要混用POSIX接口。
内容的提问来源于stack exchange,提问作者Verizz

