如何让窗口线程同时使用两个函数
How to get windows thread to work with two functions at the same time?
这个问题很简单,但解决方案我无法找到。我想调用两个函数并让它们同时运行(在不同的线程中),但我只能调用void function1()
并且void function2()
之后才运行,而不是期间。我设置了处理器 1 和 2 的线程亲缘关系(我有一个多核处理器,希望你也有一个)。
我看到一次只调用一个函数的方式仅仅是因为我得到的输出只有 function 1
,而通常我会看到 function 1
和 function 2
的混合。
随意重新洗牌代码以使其尽可能工作,但请尽量保持原始方法与类中线程调用函数的方式相同。 这是完整的代码。
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <iostream>
class thread_class
{
private:
public:
void function1()
{
for(int count = 0; count < 1000; count++)
std::cout<<"function 1"<<std::endl;
}
void function2()
{
for(int count = 0; count < 1000; count++)
std::cout<<"function 2"<<std::endl;
}
thread_class(){}
~thread_class(){}
DWORD_PTR WINAPI threadMain0()
{
function1();
return 0;
}
DWORD_PTR WINAPI threadMain1()
{
function2();
return 0;
}
void thread()
{
HANDLE *m_threads = NULL;
DWORD_PTR c = 2;
m_threads = new HANDLE[c];
DWORD_PTR i = 0;
DWORD_PTR m_id0 = 0;
DWORD_PTR m_mask0 = 1 << i;
m_threads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadMain0(), (LPVOID)i, NULL, &m_id0);
SetThreadAffinityMask(m_threads[i], m_mask0);
wprintf(L"Creating Thread %d (0x%08x) Assigning to CPU 0x%08xrn", i, (LONG_PTR)m_threads[i], m_mask0);
i = 1;
DWORD_PTR m_id1 = 0;
DWORD_PTR m_mask1 = 1 << i;
m_threads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadMain1(), (LPVOID)i, NULL, &m_id1);
SetThreadAffinityMask(m_threads[i], m_mask1);
wprintf(L"Creating Thread %d (0x%08x) Assigning to CPU 0x%08xrn", i, (LONG_PTR)m_threads[i], m_mask1);
}
};
int main()
{
thread_class* MAIN_THREADS;
MAIN_THREADS = new thread_class();
MAIN_THREADS->thread();
delete MAIN_THREADS;
return 0;
}
编辑:这是下面代码的略微修改版本,显示其未并行运行。
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <iostream>
class thread_class
{
private:
public:
void function1()
{
int exit = 0;
while(exit == 0)
{
std::cout<<"enter 1 to exit:"<<std::endl;
std::cin>>exit;
};
}
void function2()
{
for(int count = 0; count < 1000; count++)
std::cout<<"function 2"<<std::endl;
}
thread_class(){}
~thread_class(){}
DWORD_PTR WINAPI threadMain0()
{
function1();
return 0;
}
DWORD_PTR WINAPI threadMain1()
{
function2();
return 0;
}
void thread()
{
HANDLE *m_threads = NULL;
DWORD_PTR c = 2;
m_threads = new HANDLE[c];
DWORD_PTR i = 0;
DWORD_PTR m_id0 = 0;
DWORD_PTR m_mask0 = 1 << i;
m_threads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadMain0(), (LPVOID)i, NULL, &m_id0);
SetThreadAffinityMask(m_threads[i], m_mask0);
wprintf(L"Creating Thread %d (0x%08x) Assigning to CPU 0x%08xrn", i, (LONG_PTR)m_threads[i], m_mask0);
i = 1;
DWORD_PTR m_id1 = 0;
DWORD_PTR m_mask1 = 1 << i;
m_threads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadMain1(), (LPVOID)i, NULL, &m_id1);
SetThreadAffinityMask(m_threads[i], m_mask1);
wprintf(L"Creating Thread %d (0x%08x) Assigning to CPU 0x%08xrn", i, (LONG_PTR)m_threads[i], m_mask1);
}
};
int main()
{
thread_class* MAIN_THREADS;
MAIN_THREADS = new thread_class();
MAIN_THREADS->thread();
delete MAIN_THREADS;
return 0;
}
所以,有几件事:
1) 不能将常规成员函数用作 ThreadProc。 如果你必须强制转换它才能编译它,那可能是错误的。 ThreadProc 函数需要是自由的或静态的。 它们也有错误的签名,因为 ThreadProc 采用单个 void* 参数。
2)当你真正想要DWORD时,有几个地方可以使用DWORD_PTR,例如来自ThreadProc的返回值,c
,i
等。
3) 从CreateProcess
文档中:
A thread in an executable that calls the C run-time library (CRT) should use the _beginthreadex and _endthreadex functions for thread management rather than CreateThread and ExitThread; this requires the use of the multithreaded version of the CRT. If a thread created using CreateThread calls the CRT, the CRT may terminate the process in low-memory conditions.
写入cout
最终命中 CRT 的机会是。 它可能没有,即使有,你也可能没有问题,但如果你这样做,那是一个很好的地方。
4) I/O 根本不保证交错,因此写入 cout
并不是确定线程是否同时运行的好方法。 我向线程添加了一些Sleep
调用,并创建了它们最初暂停,以便我可以尽可能靠近地启动它们,以使 I/O 看起来像是交错的,但这可能只是巧合。 有一次我确实看到你可能也是,当线程启动时,打印的字符串和endl
没有相互连接,也就是说,我看到两个字符串后跟两个行尾。 在那之后,它有点交错。
5)你总是想等待线程退出,然后再从它们下面删除类。 您通常还希望在完成后关闭它们的句柄。
我删除了构造函数/析构函数,因为它们是空的和其他绒毛,只是为了尽可能保持简短。
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <iostream>
class thread_class
{
public:
void function1()
{
Sleep(0);
for(int count = 0; count < 10; count++)
{
std::cout<<"function 1"<<std::endl;
Sleep(0);
}
}
void function2()
{
Sleep(0);
for(int count = 0; count < 10; count++)
{
std::cout<<"function 2"<<std::endl;
Sleep(0);
}
}
static DWORD WINAPI threadMain0(LPVOID param)
{
thread_class* This = static_cast<thread_class*>(param);
This->function1();
return 0;
}
static DWORD WINAPI threadMain1(LPVOID param)
{
thread_class* This = static_cast<thread_class*>(param);
This->function2();
return 0;
}
void thread()
{
HANDLE m_threads[2] = {};
DWORD threadIDs[2] = {};
LPTHREAD_START_ROUTINE threadProcs[2] = {threadMain0, threadMain1};
DWORD_PTR mask = 0;
for(int i = 0; i < 2; ++i)
{
m_threads[i] = CreateThread(NULL, 0, threadProcs[i], this, CREATE_SUSPENDED, &threadIDs[i]);
mask = 1 << i;
SetThreadAffinityMask(m_threads[i], mask);
wprintf(L"Creating Thread %d (0x%08p) Assigning to CPU 0x%08prn", i, m_threads[i], mask);
}
for(int i = 0; i < 2; ++i)
{
ResumeThread(m_threads[i]);
}
WaitForMultipleObjects(2, m_threads, TRUE, INFINITE);
for(int i = 0; i < 2; ++i)
{
CloseHandle(m_threads[i]);
}
}
};
int main()
{
thread_class* MAIN_THREADS;
MAIN_THREADS = new thread_class();
MAIN_THREADS->thread();
delete MAIN_THREADS;
return 0;
}
我在代码的两个修订版中看到的问题之一是 NULL 传递给 CreateThread() 函数的 dwCreationFlags 参数。这意味着创建的线程将在 CreateThread() 退出后立即启动(如果您配备了多核 CPU 和幸运的 sheduling,甚至更快)。因此,您的第一个线程似乎在第二个线程有机会诞生之前完成了他的工作(因为线程创建在时间方面是昂贵的操作 - 数十或数百毫秒)。
因此,您可以尝试以下方法:
- 使用CREATE_SUSPENDED标志而不是 NULL 创建两个线程
- 然后调用 ResumeThread 到两个线程
- 使函数执行时间更长(可能是数百万次迭代)
- 当在同一名称空间中有两个具有相同签名的函数时,会发生什么
- 在两个类中共享相同的函数调用,并在不需要时避免空实例化
- 具有两个间接寻址运算符 (C++) 的函数参数的用途
- 如何巧妙地编写两个函数——一个用于检查是否存在解决方案,另一个用于获取所有解决方案
- 两个父类的构造函数的序列
- 具有相同特征的两个对象是否只在内存中存储一次?无论定义它们的函数是什么,都是不同的
- C++如果两个模板函数都与参数列表匹配,将调用哪个模板
- 如何从两个不同的函数传递参数
- 两个函数模板候选项.将一个参数作为引用后,选择不太专业的模板
- 如何比较两个函数的速度和性能
- 是否可以使用非常量指针调用非常量函数,以及当两个unique_ptrs指向同一个对象时程序的行为方式?
- 有一个构造函数,但有两个析构函数
- 为什么系统日志有两个不同的函数声明?
- 为什么在传递长整型时调用具有两个双精度类型的参数的重载函数?
- C++ 关于两个类构造函数的问题
- 如何创建两个具有相同名称和不同返回类型并基于布尔参数运行的函数
- 如何在构造器的成员初始值设定项列表中调用两个函数?
- 如何将这两个函数组合成一个实现?
- 将函数两个向量合并为第三个向量
- C++朋友函数两个数字的加法