【问题标题】:How to return a char * from a Windows Thread function如何从 Windows Thread 函数返回 char *
【发布时间】:2018-01-10 06:48:51
【问题描述】:

您好,这是一个多层次的问题,但基本上我希望我的线程函数返回一个 char *,然后我希望能够在线程终止后访问该结果。

目前,我在线程函数的末尾将 char * 类型转换为 DWORD,例如:(openPorts is my char *)

DWORD openPortsD = (DWORD)openPorts;

然后立即返回 openPortsD。但这似乎不起作用。

我的线程创建逻辑如下:

for (int j = 0; j < MAX_THREADS; j++)
{
  pDataArray[j] = (PMYDATA) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MYDATA));

  if(pDataArray[j] == NULL)
  {
      ExitProcess(2);
  }
  pDataArray[j]->ip = ip;

  hThreadArray[j] = CreateThread(NULL, 0, connectPortW,  pDataArray[j], 0, &dwThreadIdArray[j]);

  if (hThreadArray[j] == NULL) 
  {
     ExitProcess(3);
  }
}

在我遍历我的线程之后,我等待我的线程,然后像这样释放/关闭它们:

WaitForMultipleObjects(MAX_THREADS, hThreadArray, TRUE, INFINITE);

for(int j = 0; j < MAX_THREADS; j++)
{
  CloseHandle(hThreadArray[j]);
  if(pDataArray[j] != NULL)
  {
    HeapFree(GetProcessHeap(), 0, pDataArray[j]);
    pDataArray[j] = NULL;    // Ensure address is not reused.
  }
}

现在第二部分是如何获取返回值。我知道我应该使用 GetExitCodeThread() 但我不确定如何将它用于运行的多个线程。此外,由于返回值将是一个 DWORD 我如何取回我的原始字符串?

【问题讨论】:

  • 使用线程退出代码让生活变得更加困难。您可以像处理数据一样执行此操作(pDataArray,大小与线程数相同——所以创建一个pResultArray,线程写入而不是读取)
  • 退出代码是DWORD - 4 字节,当指针可以是 8 字节时(在 64 位代码中)。所以指针已经不适合退出代码。你将一些对象传递给线程 - 所以线程并且必须在这个对象中返回结果
  • 如果这是一个 GUI 应用程序,将字符串从工作线程传递到主线程的方法是在堆上分配该字符串(运算符 new 用于 C++ 或 malloc 用于 C)然后通过在WM_APP-type 消息中将其发布到主线程(使用PostMessage API。)然后您的主线程可以处理该消息并释放字符串。
  • @ahmd0:这是该问题的一个解决方案,它不需要 GUI 应用程序。如果数据跨越 DLL 边界,newmalloc 就会出现问题。 HeapAlloc 在这方面已经做得更好了。
  • 您正在将线程指针传递给数据结构 (MYDATA)。为什么不直接将 char* 作为 char* 存储为 MYDATA 成员?

标签: c windows multithreading winapi


【解决方案1】:

您已经将一个结构传递给线程,最好的解决方案是向其中添加一个字段以供线程填充。

typedef struct {
  const char *ip;
  const char *openports;
} MYDATA, *PMYDATA;

DWORD CALLBACK connectPortW(LPVOID ThreadParam)
{
  PMYDATA data = (PMYDATA) ThreadParam;
  data->openports = allocatestringandfillitwithlistofports(data->ip);
  return 0;
}

...

WaitForMultipleObjects(MAX_THREADS, hThreadArray, TRUE, INFINITE);
for(int j = 0; j < MAX_THREADS; j++)
{
  CloseHandle(hThreadArray[j]);
  if(pDataArray[j] != NULL)
  {
    parseandfreeports(pDataArray[j]);
    HeapFree(GetProcessHeap(), 0, pDataArray[j]);
    pDataArray[j] = NULL;    // Ensure address is not reused.
  }
}

如果这是一个 IP 端口列表,那么最好将端口存储在 SHORT 数组中而不是字符串中。

如 cmets 中所述,您可以分配一些内存并将其作为 32 位应用程序中的线程退出代码返回,但由于 64-it 指针不适合 4 个字节,因此无法将其移植到 64 -位。

【讨论】:

    猜你喜欢
    • 2020-02-21
    • 2011-08-05
    • 2021-02-14
    • 1970-01-01
    • 2010-12-23
    • 2018-10-18
    • 1970-01-01
    • 2021-08-14
    相关资源
    最近更新 更多