Windows应用程序线程
线程是进程中的⼀个执⾏单元,负责当前进程中程序的执⾏,⼀个进程中⾄少有⼀个线程。⼀个进程中是可以有多个线程的,这个应⽤程序也可以称之为多线程程序。线程可能是通过时间片调度器准虚拟并行执行,或者通过在不同CPU核心上真正并行执行。Kithara RealTime Suite提供了一些用于线程处理的函数。
请注意,我们区分“线程”和“任务”,尽管这两种机制是可比较的:
- “线程”是Windows的(非实时)并行化概念
- “任务”是Kithara RealTime Suite的并行化概念
为了避免混淆这两个概念。线程在Windows应用程序上下文中运行,而任务在Kithara的实时上下文中运行。
线程函数的原型
为了生成一个线程,必须提供一个函数,该函数将作为线程函数工作。此函数的代码将在操作系统上与其他正在运行的线程并行执行。线程函数的原型是:
C/C++:
Error __stdcall threadFunction(void* pArgs);
Delphi:
function threadFunction(pArgs: Pointer): Error; stdcall;
在C/C++和Delphi中,函数必须按照stdcall调用约定定义!
引用参数pArgs可以用作任何数据结构的引用,作为线程函数所需的。最方便的方法是将数据结构的引用传递给线程函数。
创建线程
要创建线程,需要预定义线程函数。将线程函数的地址与引用参数pArgs一起传递给KS_createThread中的procName。使用phThread可以检索已创建线程的Windows线程句柄(请仔细阅读对KS_createThread的引用!)
可以使用函数KS_setThreadPrio更改线程优先级。
移除线程
当线程不再使用时,通过KS_createThread创建的所有线程必须调用KS_removeThread以释放所有已使用的资源。
管理线程优先级
Kithara RealTime Suite提供了设置线程优先级的。在这里,可以指定绝对优先级,这与相应的Windows API函数不同。Windows提供了32个优先级步骤,其值在0和31之间。较高的值定义了较高的优先级。在Kithara中值在16和31之间属于实时,意味着操作系统不会对线程优先级进行动态调整。
函数KS_setThreadPrio的优点是它避免了许多经常遇到的死锁情况。普通Windows应用程序要想获得更高的优先级级别的唯一方法是先将整个应用程序设置为REALTIME_PRIORITY_CLASS。这很容易导致应用程序死锁!
设置线程优先级设置为更高的值会抢占普通 Windows 线程。
设置线程优先级
KS_setThreadPrio用于设置绝对线程优先级。此函数需要在线程上下文中调用。
读取当前线程优先级,要查询当前线程优先级,可以使用KS_getThreadPrio。
项目实例
#include <iostream>
#include <KrtsDemo.h>
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
const char customerNumber[256] = "DEMO";
bool is_thread_run = false; // 判断线程是否还在运行
void OutputErr(KSError error, const char* pFuncName, const char* pComment)
{
if (error == KS_OK)
return;
const char* pError;
KS_getErrorString(error, &pError, KSLNG_DEFAULT);
printf("ERROR (%08X = \'%s\') - %s: %s\n", error, pError, pFuncName, pComment);
}
// 线程函数
KSError __stdcall ThreadFunction(void* pArgs)
{
// 设置线程优先级
KSError error = KS_setThreadPrio(15);
if (error != KS_OK)
{
OutputErr(error, "KS_setThreadPrio", " set thread prio error!");
KS_closeDriver();
return error;
}
uint prio;
KS_getThreadPrio(&prio);
is_thread_run = true;
int x = 0;
while (true)
{
if (++x >5)
{
is_thread_run = false;
break;
}
else
{
printf("ThreadFunction %d ThreadPrio %d \n",x, prio);
Sleep(1000);
}
}
// 资源释放
//error = KS_removeThread();
//if (error != KS_OK)
//{
// OutputErr(error, "KS_removeThread", "");
// return error;
//}
return KS_OK;
}
int main()
{
KSError error;
error = KS_openDriver(customerNumber); // 所有Kithar项目的第一步
if (error != KS_OK)
{
error = 1;
OutputErr(error, "KS_openDriver", "Unable to open the driver!");
}
else
{
printf("Hello Kithara! \n");
}
// 创建一个线程
error = KS_createThread(ThreadFunction, nullptr, nullptr);
if (error != KS_OK)
{
OutputErr(error, "KS_createThread"," Create thread error!");
KS_closeDriver();
return error;
}
Sleep(1000);
while (is_thread_run)
{
uint prio;
KS_getThreadPrio(&prio);
printf("Wait thread end Main Prio %d\n", prio);
Sleep(1000);
}
// 资源释放
error = KS_closeDriver();
if (error != KS_OK)
{
OutputErr(error, "KS_closeDriver", "");
KS_closeDriver();
return error;
}
Sleep(1000);
return 0;
}
更多示例,请查看:
smp\CameraImageAcquisition
smp\CameraWithLinkAggregation
smp\CanFDRecv, smp\NetworkEthernetMonitor
smp\NetworkEthernetReceive
smp\NetworkEthernetSend
smp\NetworkTcpServer
smp\NetworkUdpReceive
smp\SerialUartTerminal
smp\UsbHidKeyboard
smp\UsbHidMouse
smp\XhciHidKeyboard
smp\XhciHidMouse.