gpt4 book ai didi

C++ Win32数据处理线程

转载 作者:行者123 更新时间:2023-11-30 05:40:12 25 4
gpt4 key购买 nike

我编写了一个 Win32 异步客户端应用程序,我想创建一个线程来单独处理传入的数据。我对以下代码有疑问。线程已启动,获取一些数据但未正常运行(数据不完整)。我看不出问题出在哪里。你能帮帮我吗?

void incData(void *arg) // This is the thread
{
WaitForSingleObject(hIncDataMutex, INFINITE);

char *sRead = _strdup(sReadBuffer.c_str());
appendTextToEdit(hDebug, sRead); // Some data is displayed, but incompletely
string var;
char *pVar = nullptr;
char *next_token = nullptr;

istringstream iss(sReadBuffer); // sReadBuffer is the global variable I use to pass argument to my thread

while (getline(iss, var)) // Default delimiter '\n'
{
pVar = _strdup(var.c_str()); // Cast string to char *
appendTextToEdit(hDebug, pVar);
appendTextToEdit(hDebug, "\n");

if(strstr(pVar, "id=") != NULL)
{
char *label = strtok_s(pVar, "=", &next_token);
char *pId = strtok_s(NULL, "\n", &next_token);
strcpy_s(id, pId);
}

if( strstr(pVar, "version") != NULL)
{
char *label = strtok_s(pVar, "=", &next_token);
char *pVersion = strtok_s(NULL, "\n", &next_token);
strcpy_s(version, pVersion);
}

if( strstr(pVar, "Qh57=") != NULL)
{
char *label = strtok_s(pVar, "=", &next_token);
char *pFoFd = strtok_s(NULL, "\n", &next_token);
strcpy_s(foFd, pFoFd);
}
}
ReleaseMutex(hIncDataMutex);
}

//.....

case FD_CONNECT: // I launch the thread here (I want it to run forever in the background)
{
connectStatus = TRUE;
statusText=TEXT("Connected");

hIncDataMutex = CreateMutex(NULL, false, NULL); // Create incoming data process thread mutex
HANDLE hThread2 = (HANDLE)_beginthread(incData, 0, 0); // Launch incoming data process thread
}

//....

case FD_READ:
{
int bytes_recv = recv(Socket, readBuffer, sizeof(readBuffer), 0);

sReadBuffer = readBuffer; // Copy the buffer to global scope string (used to feed thread)

ReleaseMutex(hIncDataMutex);
}
break;

编辑

这是我的带有新调试行的代码,以及调试窗口的输出:

void incData(void *arg)
{
WaitForSingleObject(hIncDataMutex, INFINITE);
appendTextToEdit(hDebug, "Inside thread...\n");


string var;
char *pVar = nullptr;
char *next_token = nullptr;

istringstream iss(sReadBuffer); // Put into a stream

while (getline(iss, var)) // Default delimiter '\n'
{
pVar = _strdup(var.c_str()); // Cast string to char *

if(strstr(pVar, "id=") != NULL)
{
char *label = strtok_s(pVar, "=", &next_token);
char *pId = strtok_s(NULL, "\n", &next_token);
strcpy_s(id, pId);
}

if( strstr(pVar, "version") != NULL)
{
char *label = strtok_s(pVar, "=", &next_token);
char *pVersion = strtok_s(NULL, "\n", &next_token);
strcpy_s(version, pVersion);
}

if( strstr(pVar, "Qh57=") != NULL)
{
char *label = strtok_s(pVar, "=", &next_token);
char *pFoFd = strtok_s(NULL, "\n", &next_token);
strcpy_s(foFd, pFoFd);
appendTextToEdit(hDebug, "Qh57=");
appendTextToEdit(hDebug, foFd);
appendTextToEdit(hDebug, "\n");
}
}

ReleaseMutex(hIncDataMutex);
appendTextToEdit(hDebug, "Mutex released by thread\n");
}

//....

case FD_READ:
{
appendTextToEdit(hDebug, "FD_READ event\n");


int bytes_recv = recv(Socket, readBuffer, sizeof(readBuffer), 0);
appendTextToEdit(hDebug, "Bytes reveived\n");
sReadBuffer = readBuffer; // Copy the buffer to string
ReleaseMutex(hIncDataMutex);
appendTextToEdit(hDebug, "End of FD_READ\n");
}
break;

从调试窗口:

FD_CONNECT, begining thread
FD_READ event
Bytes reveived
End of FD_READ
FD_READ event
Bytes reveived
End of FD_READ
Inside thread... // Thread is only called here !
FD_READ event
Bytes reveived
End of FD_READ
Mutex released by thread // Thread ends here
FD_READ event
Bytes reveived
End of FD_READ

等等...有什么想法吗?

最佳答案

我认为这是因为您在互斥量上等待数据的方式:将其设置在一侧,而从不尝试将其设置在另一侧,这清楚地表明缺少某些东西。

这是可能发生的情况:

main thread                         processing thread
--------------------------------------------------
data A is received on FD_READ waiting on mutex
ReleaseMutex() ---> start processing the data A
other data B is received ..
ReleaseMutex() .. end processing data A
still other C data overwrites B ReleaseMutex()
ReleaseMutex() waiting on mutex
processing data C which has overwriten B
( ==> B is lost)

避免接收数据,除非您可以以不会覆盖尚未处理的数据的方式缓冲数据。这通常需要在更新(填充)共享数据时(即在尝试复制缓冲区之前)设置互斥锁。 This tutorial至少从设计原则来看,您可能会感兴趣。

重要修改:

与多线程无关,但不要忘记 recv()不保证以空字符结尾的字符串。所以在将它复制到一个字符串之前,检查错误并放置一个尾随的'\0'。因此,作为第一步,您可以尝试:

case FD_READ:
{
int bytes_recv = recv(Socket, readBuffer, sizeof(readBuffer),
0);
if (bytes_recv!=SOCKET_ERROR) {
readBuffer[bytes_recv] = '\0'; //... trailing null
WaitForSingleObject(hIncDataMutex, INFINITE);
sReadBuffer = readBuffer; // Copy the buffer to global scope string (used to feed thread)

ReleaseMutex(hIncDataMutex);

}
else cout << "Socket error";
...

关于C++ Win32数据处理线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31832107/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com