- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有点困惑为什么 _beginthreadex()
没有启动我的线程。基本上,我有一个线程:
编辑 #3 -- 添加了 while() 作为我代码的一部分,但我最初从未声明过,因此该线程必须始终运行,直到在内部提示退出代码它。而且它必须与我的实际应用程序一起运行(因此,我实际上不能 WaitForSingleObject(HANDLE, INFINITE)
)
unsigned int WINAPI MyThread1(LPVOID)
{
MessageBoxA(0, "We're in!", 0, 0);
while (TRUE)
{
// do something
}
}
我有我的 _beginthreadex()
代码:
/*
take note that, this is inside another function, and that function is also
called through a seperate _beginthreadex() call, so basically, this thread
is supposed to be called from within another thread
*/
if (user.settingsPage.ChangeVolume > 0)
{
_beginthreadex(0, 0, &MyThread1, 0, 0, 0);
// do some cleanup here, of non-related things
}
这个文件是一个 DLL 扩展。
为什么线程永远不会运行,换句话说,当 _beginthreadex()
时,为什么我从来没有看到 MessageBoxA()
出现在我的屏幕上通过?是不是不能在 DLL 文件中使用 _beginthreadex()
还是什么?
编辑#1
我已经实现了 Richard Chambers
在他的回复中所说的内容。
我从GetExitCodeThread()
得到了错误码,并在MessageBoxA()
中输出,错误码输出为259
。
查看 MSDN 系统错误代码列表后:here
错误码对应如下:
ERROR_NO_MORE_ITEMS
259 (0x103)
No more data is available.
编辑#2
我正在阅读 here ,并且我注意到此文本 如果线程返回 STILL_ACTIVE (259) 作为错误代码,测试此值的应用程序可以将其解释为表示线程仍在运行并在之后继续测试线程是否完成线程已终止,这可能会使应用程序陷入无限循环。
-- 这与我的问题有什么关系吗?如果是这样,线程仍在运行
是什么意思?如果它已经在运行,那么为什么我在 MessageBox 中看不到它的任何输出或它的其余内容?
那么,有了这些结论,我该怎么办?我该如何解决这个问题?
最佳答案
下面是两个在 Visual Studio 2012 中作为控制台应用程序编译和运行的简单示例。创建一个简单的 Windows 控制台应用程序,然后将此源代码粘贴到该文件中。错误检测方式不多,但主要部分有效。
_beginthreadex()
为 Windows API 中的 CreateThread()
提供了一个包装器,但是文档表明它为 C/C++ 运行时执行必要的启 Action 为一部分启动线程。参见 Windows threading: _beginthread vs _beginthreadex vs CreateThread C++详细了解这三种在 Windows 中启动线程的方式之间的区别。
在 DLL 和 COM 对象中一直使用启动线程,所以还有其他错误。以下示例一次启动一个线程。
// threadtest.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
// necessary include files for a Console application wanting to do some Windows things with threads.
// ordinarily #include <Windows.h> would be added to stdafx.h for this Console application.
// Windows.h provides things such as the Sleep() function as well as definitions for HANDLE, etc.
// process.h provides the prototypes and declarations for _beginthreadex()
// iostream with no .h provides the C++ Standard Library I/O routines for std::cout
#include <Windows.h>
#include <process.h>
#include <iostream>
// list of arguments to provide to the thread being started up.
struct argList {
int i1;
int i2;
int i3;
};
unsigned int WINAPI myThread (void * args)
{
argList *pArgs = (argList *)args; // convert the LPVOID to the proper type to access the arguments.
// a bit of output to let us know we got here then a sleep to slow things down a touch.
std::cout << "myThread is running? args " << pArgs->i1 << ", " << pArgs->i2 << ", " << pArgs->i3 << std::endl;
Sleep(1000);
// add the arguments and return the sum.
return (pArgs->i1 + pArgs->i2 + pArgs->i3);
}
// declare the function in the DLL we are going to call.
__declspec(dllimport) HANDLE __cdecl Function1(void);
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hThread;
DWORD exitCode;
argList myArgs = {1, 2, 3};
std::cout << "main is running?" << std::endl;
// start a thread with the arguments we want to sum and wait for it to complete and return to us.
// when it returns we will fetch the return value which is the sum of the arguments.
hThread = (HANDLE)_beginthreadex (0, 0, myThread, &myArgs, 0, 0);
WaitForSingleObject (hThread, INFINITE); // Wait for the thread we started to complete, a kind of Join
GetExitCodeThread (hThread, &exitCode); // Get the thread's exit code so that we can print it out
CloseHandle (hThread); // We be done with the thread so close out it's handle to release resources
std::cout << "main ending, thread exit code " << exitCode << std::endl;
// now call the function in our DLL which will start up a thread there
// get its handle so that we can check the exit code, etc.
hThread = Function1();
WaitForSingleObject (hThread, INFINITE); // Wait for the thread we started to complete, a kind of Join
GetExitCodeThread (hThread, &exitCode); // Get the thread's exit code so that we can print it out
CloseHandle (hThread); // We be done with the thread so close out it's handle to release resources
std::cout << "main ending, Function1 exit code " << exitCode << std::endl;
return 0;
}
已使用标准添加向导将一个简单的控制台 DLL 项目添加到 Visual Studio 2012 解决方案中。我修改了一个空文件,而不是包含附加 DLL 消息处理程序等的 DLL 主文件。修改后的文件包含以下内容:
#include "stdafx.h"
#include <Windows.h>
#include <process.h>
#include <iostream>
unsigned int WINAPI myThread2 (void * args)
{
// a bit of output to let us know we got here then a sleep to slow things down a touch.
std::cout << "myThread2 is running? args " << std::endl;
MessageBox (0, L"A message2 text", L"Caption 2", 0);
Sleep(1000);
// add the arguments and return the sum.
return 345;
}
__declspec(dllexport) HANDLE __cdecl Function1(void)
{
std::cout << " in DLL, starting thread." << std::endl;
HANDLE hThread = (HANDLE)_beginthreadex (0, 0, myThread2, 0, 0, 0);
return hThread;
}
多线程
如果简单的应用程序被修改为在输出线程中有循环,我们可以同时运行多个线程。 main 可以修改为如下所示,我们启动两个我们有兴趣管理的不同线程,然后等待两个线程完成,然后检查两个线程的退出状态,如下所示。第三个线程已启动,但我们既不获取它的句柄也不管理它。它运行很短的时间然后结束。
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hThreads[2];
DWORD exitCode;
unsigned int threadId;
argList myArgs = {1, 2, 3};
std::cout << "main is running?" << std::endl;
// start a thread with the arguments we want to sum and wait for it to complete and return to us.
// when it returns we will fetch the return value which is the sum of the arguments.
hThreads[0] = (HANDLE)_beginthreadex (0, 0, myThread, &myArgs, 0, &threadId);
hThreads[1] = Function1();
WaitForMultipleObjects (2, hThreads, TRUE, INFINITE); // Wait for all threads we started to complete, a kind of Join
GetExitCodeThread (hThreads[0], &exitCode); // Get the thread's exit code so that we can print it out
std::cout << "main ending, thread 1 exit code " << exitCode << std::endl;
GetExitCodeThread (hThreads[1], &exitCode); // Get the thread's exit code so that we can print it out
std::cout << "main ending, thread 2 exit code " << exitCode << std::endl;
CloseHandle (hThreads[0]); // We be done with the thread so close out it's handle to release resources
CloseHandle (hThreads[1]); // We be done with the thread so close out it's handle to release resources
return 0;
}
三个线程中的每一个都有一个简单的循环,该循环计算最终值并向标准输出显示一条消息。 Sleep(1000)
为我们提供了一种降低一切速度的方法。所以每个线程都有一个循环,如下所示,它来自线程号 3。
MessageBox (0, L"A message 3 text", L"Caption 3", 0);
std::cout << " myThread 3 after MessageBox - start loop" << std::endl;
for (int i = 0; i < 10; i++) {
Sleep(1000);
std::cout << " myThread 3 is running step "<< i << std::endl;
}
std::cout << "myThread 3 end" << std::endl;
此示例的 DLL 源在导出的入口点 Function1()
中启动一个线程,在 Function1()
中启动的线程启动第三个线程。
#include "stdafx.h"
#include <Windows.h>
#include <process.h>
#include <iostream>
unsigned int WINAPI myThread3 (void * args)
{
// a bit of output to let us know we got here then a sleep to slow things down a touch.
std::cout << "myThread3 is running? args " << std::endl;
MessageBox (0, L"A message 3 text", L"Caption 3", 0);
std::cout << " myThread 3 after MessageBox - start loop" << std::endl;
for (int i = 0; i < 10; i++) {
Sleep(1000);
std::cout << " myThread 3 is running step "<< i << std::endl;
}
std::cout << "myThread 3 end" << std::endl;
return 2356;
}
unsigned int WINAPI myThread2 (void * args)
{
// a bit of output to let us know we got here then a sleep to slow things down a touch.
std::cout << "myThread2 is running? args " << std::endl;
MessageBox (0, L"A message 2 text", L"Caption 2", 0);
std::cout << " myThread 2 after MessageBox - start myThread3 then loop" << std::endl;
HANDLE hThread = (HANDLE)_beginthreadex (0, 0, myThread3, 0, 0, 0);
for (int i = 0; i < 10; i++) {
Sleep(1000);
std::cout << " myThread 2 is running "<< i << std::endl;
}
std::cout << "myThread 2 end" << std::endl;
// add the arguments and return the sum.
return 345;
}
__declspec(dllexport) HANDLE __cdecl Function1(void)
{
std::cout << " in DLL, starting myThread 2." << std::endl;
HANDLE hThread = (HANDLE)_beginthreadex (0, 0, myThread2, 0, 0, 0);
return hThread;
}
输出显示了所有正在运行的线程。请注意,在输出中,由线程 2 启动的线程 3 在线程 2 由于启动其循环的延迟而结束后继续运行。线程2和线程3都在DLL代码中,在main调用Function1()
的DLL入口点时启动。
main is running?
in DLL, starting myThread 2.
myThread is running? args myThread2 is running? args 1, 2, 3
myThread after MessageBox - start loop
myThread is running i = 0
myThread is running i = 1
myThread 2 after MessageBox - start myThread3 then loop
myThread3 is running? args
myThread is running i = 2
myThread 2 is running 0
myThread is running i = 3
myThread 2 is running 1
myThread is running i = 4
myThread 3 after MessageBox - start loop
myThread 2 is running 2
myThread is running i = 5
myThread 3 is running step 0
myThread 2 is running 3
myThread is running i = 6
myThread 3 is running step 1
myThread 2 is running 4
myThread is running i = 7
myThread 3 is running step 2
myThread 2 is running 5
myThread is running i = 8
myThread 3 is running step 3
myThread 2 is running 6
myThread is running i = 9
myThread 3 is running step 4
myThread 2 is running 7
myThread is running i = 10
myThread 3 is running step 5
myThread 2 is running 8
myThread is running i = 11
myThread 3 is running step 6
myThread 2 is running 9
myThread 2 end
myThread is running i = 12
myThread 3 is running step 7
myThread is running i = 13
myThread 3 is running step 8
myThread is running i = 14
myThread 3 is running step 9
myThread 3 end
myThread is running i = 15
myThread is running i = 16
myThread is running i = 17
myThread is running i = 18
myThread is running i = 19
myThread end
main ending, thread 1 exit code 6
main ending, thread 2 exit code 345
关于C++ - _beginthreadex() 不启动线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32673772/
每当我运行命令以将 Virtualbox 驱动程序启动 Minishift 到操作系统主机时,它都需要一段疯狂的时间,而且它永远不会结束。有时我什至收到有关达到存储限制的错误消息。 不知道是不是描述h
您好,我正在使用 npm 运行一个基本的 React 项目,我正尝试在 docker 容器中启动它。但是我实际上无法让项目运行。我的 dockerfile 看起来像这样: FROM node:7.8.
所以我想从我的 SSH 终端开始游戏。 这真的很奇怪,当我直接从 Linux GUI 执行此操作时,它可以工作。但是当我使用 SSH 客户端进行远程连接时,它就崩溃了。似乎与我的显示驱动程序有关。 U
我有一个显示图像的动态壁纸。我在 Activity 中更改了该图像。然后我需要通知动态壁纸,以便它知道重新加载资源。 Intent 似乎是完美、简单的解决方案: Intent intent = new
我有一个似乎无法解决的问题。我在 Boot Dashboard 中使用 STS 3.9.2 从 Eclipse (Oxygen) 启动 Spring Boot 应用程序没有任何问题: 但是,当我尝试从
全新的 Python,在我开始摆弄东西之前先设置和安装东西。我的理解是 Python 2.7 和 Python 3.3 之间存在一些显着差异/不兼容,尽管这两个版本都得到了很好的使用,所以我认为最好安
在使用了很长时间的 jQuery 之后,我有一个问题,我正在使用 jQuery 模式(样式)编写一个简单的代码, (function(window, undefined) { var jQu
我正在尝试在 spring boot 应用程序下的非 spring 托管类中配置 Autowired。我在 tomcat 服务器下部署的 Web 应用程序下成功运行了这个。但是当我想在 spring
我对 xmonad 完全陌生,但我想开始使用它来提高我的工作效率。 这是我一直在使用的指南(我使用的是 Apple OS X Snow Leopard) http://xmonad.org/tour.
我试图将Spring Boot指南中的Managing Transactions示例扩展到两个数据源,但是@Transaction注释似乎仅对其中一个数据源有效。 在“Application.java
conEmu 有没有办法默认打开多个不同的选项卡? 我看到这个页面解释了如何使用 splits , 我意识到我可以按 Ctrl + T, 1, Enter,但我希望有一种方法可以自动执行此操作! "%
我正在寻找快速而肮脏的答案。我当时脑子一片空白,盯着屏幕看了 12 个小时以上,我想我中枪了。 我想做一个简单的 SignalR 应用程序作为教程。我找到了这个example ,但我不断收到票证未定义
我正在使用 Azure Powershell cmdlet 来启动/停止 VM。 Start-AzureVM [-ServiceName] [-Name] [ ] Stop-AzureVM [-S
我想使用Powershell脚本代码启动/停止iis和mssql 意味着当我运行ps脚本时,我想启动/停止iis和mssql 我在网上搜索了它,发现了一些代码,但按照我的要求无法正常工作 码: $ii
我在 liferay 工作。我们在我们的项目中使用一个模块来创建 liferay 主题。我使用命令 ant -Ddeploy.war=true 将它部署在服务器中。 war 文件在 liferay 部
我想在已安装 Python 2.7 的 Windows XP 计算机上运行 IPython(版本 0.12)。 我通过 Windows 二进制安装程序安装,但安装后 IPython 没有显示在菜单中,
我从创建了自己的简单图片。 FROM python:2.7.11 RUN mkdir /extra/later/ \ && mkdir /yyy 现在,我可以执行以下步骤: docker run
$(document).ready(function () { setTimeout(function() { window.location.reload(); }, 2000); // 2
我刚刚创建了一个帐户 OpenWeatherMap 我想通过城市 ID API 调用获取当前位置的天气: http://api.openweathermap.org/data/2.5/weather?
我注意到,如果我更改 xcasset 中的图像,启动 Storyboard不会更新。 例如,假设您的启动 Storyboard中有一个 UIImage View ,其中包含一个名为“logo”的蓝色图
我是一名优秀的程序员,十分优秀!