代码如下
// 进程A 创建命名的 event,并设置husing 为授信,最后等待hexit 事件,退出
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
HANDLE hExitEvent = ::CreateEvent(&sa,false,false,TEXT("_hExitEvent"));
HANDLE husedEvent = ::CreateEvent(&sa,false,false,TEXT("_hUsedEvent"));
STARTUPINFO si;
ZeroMemory(&si,sizeof(si));
si.cb=sizeof(STARTUPINFO);
PROCESS_INFORMATION pi;
if(!CreateProcess(NULL,TEXT("ChildProcess.exe"),NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
{
cout<<"failed to run chilld process"<<endl;
}
::SetEvent(husedEvent);
cout<<"Reset HUSEDEVENT" <<endl;
Sleep(100);
::WaitForSingleObject(hExitEvent,INFINITE);
system("PAUSE");
return 0;
进程B
//B等待husing 事件,然后设置 hexit 事件授信,推出.
HANDLE hEvent_exit = ::OpenEvent(NULL,false,TEXT("_hExitEvent"));
HANDLE hTestEvent = ::OpenEvent(NULL,false,TEXT("_hUsedEvent"));
::WaitForSingleObject(hTestEvent,INFINITE);
cout<<"recive the message from parent!"<<endl;
SetEvent(hEvent_exit);
Sleep(50);
现在问题是,B能收到事件husing,然后设置hexit,退出了,但是进程A 还在哪等待hExit 事件,而且是一直等待。
那个高人回答下为什么呢?
27 个解决方案
#1
有没有其他线程或者进程reset hEvent_exit
CEvent::SetEvent
BOOL SetEvent();
返回值:如果操作成功,则返回非零值,否则为0。
说明:
设置事件的状态为有标记,释放任意等待线程。如果事件是手工的,此事件将保持有标记直到调用 ResetEvent。这种情况下将释放多个线程,如果事件是自动的,此事件将保持有标记,直到一个线程被释放,系统将设置事件的状态为无标记。如果没有线程在等待,则此事件将保持有标记,直到一个线程被释放。
CEvent::SetEvent
BOOL SetEvent();
返回值:如果操作成功,则返回非零值,否则为0。
说明:
设置事件的状态为有标记,释放任意等待线程。如果事件是手工的,此事件将保持有标记直到调用 ResetEvent。这种情况下将释放多个线程,如果事件是自动的,此事件将保持有标记,直到一个线程被释放,系统将设置事件的状态为无标记。如果没有线程在等待,则此事件将保持有标记,直到一个线程被释放。
#2
问题解决。 散分了,来人给分,晚上结贴
#3
GX .
#4
我是进来学习的。
#5
JF...
#6
我来接分
#7
来接分了
#8
顺便说下你的问题所在,解决办法是什么
#9
来接分了
#10
来接分了
#11
咋解决的啊。。。
#12
UP~~~
#13
楼主也不说说是怎么回事哦。。。
让我过下瘾吧。
让我过下瘾吧。
#14
问题确实被解决了,但是仍然存在困惑,高人可以解答下
1:使用命名句柄方法,A 进程创建 通信句柄时候去掉权限的限制,如下CreateEvent第一个参数为NULL
进程B 使用createEvent “创建”同样命名的句柄
这个时候通信成功了,比较疑惑,如果我使用OPenEvent 打开句柄就不行,getlasterror 提示为0;
以上是我现在使用的解决方案,不过命名换成了不冲突的,是一个初级解决方案。
1:使用命名句柄方法,A 进程创建 通信句柄时候去掉权限的限制,如下CreateEvent第一个参数为NULL
HANDLE hExitEvent = ::CreateEvent(NULL,false,false,TEXT("_hExitEvent"));
HANDLE husedEvent = ::CreateEvent(NULL,false,false,TEXT("_hUsedEvent"));
STARTUPINFO si;
ZeroMemory(&si,sizeof(si));
si.cb=sizeof(STARTUPINFO);
PROCESS_INFORMATION pi;
if(!CreateProcess(NULL,TEXT("ChildProcess.exe"),NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
{
cout<<"failed to run chilld process"<<endl;
}
::SetEvent(husedEvent);
cout<<"send message to parent!" <<endl;
Sleep(100);
::WaitForSingleObject(hExitEvent,INFINITE);
cout<<"Answered by other process!\n";
system("PAUSE");
return 0;
进程B 使用createEvent “创建”同样命名的句柄
HANDLE hExitEvent = ::CreateEvent(NULL,false,false,TEXT("_hExitEvent"));
if(::GetLastError() ==ERROR_ALREADY_EXISTS )
{
cout<<"HANDLE is created by another process\n";
}
HANDLE husedEvent = ::CreateEvent(NULL,false,false,TEXT("_hUsedEvent"));
::WaitForSingleObject(husedEvent,INFINITE);
cout<<"recive the message from parent!"<<endl;
SetEvent(hExitEvent);
Sleep(50);
return 0;
这个时候通信成功了,比较疑惑,如果我使用OPenEvent 打开句柄就不行,getlasterror 提示为0;
以上是我现在使用的解决方案,不过命名换成了不冲突的,是一个初级解决方案。
#15
第2个解决方案比较简单
通过继承句柄来通信的。
我大致说下
CreateEvent()的第一个参数初始化一下。并传入,
然后在进程A中(父进程)创建子进程时候选择可以继承,并且在cmdline 中传入事件的内核地址
进程B中,解析Argv[1],解释成一个地址,赋给一个HANDLE,setEvent 这个handle通知进程A退出
这个方法虽然能通信,但是太失败。。。
通过继承句柄来通信的。
我大致说下
CreateEvent()的第一个参数初始化一下。并传入,
然后在进程A中(父进程)创建子进程时候选择可以继承,并且在cmdline 中传入事件的内核地址
进程B中,解析Argv[1],解释成一个地址,赋给一个HANDLE,setEvent 这个handle通知进程A退出
这个方法虽然能通信,但是太失败。。。
#16
设置权限的话,进程B应该打开某些权限吧。
顺便接分。
顺便接分。
#17
没考虑用PossthreadMessage ?
#18
我OPenEvent设置的是那个sync(线程同步类的)权限。GetLastError 提示 为0 ,这时候就跟我帖子的问题一样了,B退出了,A始终在等待。说明B收到了消息,但是,A没收到?
#19
铅哥,说的高级了。我菜的很。吃饭回来试试。米饭去了先
#20
这个好用,不高级的。用几用就熟悉了,要不要我写段代码来测试。。。
#21
接分了!呵呵
#22
哈哈,我先试试。我先探探MSDN
#23
那好的,呵呵
#24
我帮你写了个简单的程序,大致是:
在主进程中创建一个子进程和一个线程,线程里处理消息本进程的消息和子进程返回的消息。
PossThreadMessage, 函数的的最后两个参数可以用作想要传递的数据。
在主进程中创建一个子进程和一个线程,线程里处理消息本进程的消息和子进程返回的消息。
PossThreadMessage, 函数的的最后两个参数可以用作想要传递的数据。
#25
MainProc.cpp
ChildProc.cpp
#include <Windows.h>
#include <process.h>
const UINT MS_OPENFINISHED = WM_USER+8001;
const UINT MS_RUN = MS_OPENFINISHED + 1; //子进程的消息
const UINT MS_RETURN = MS_RUN + 1;
wchar_t g_wcControl = L'\0';
unsigned int g_dwControlThread = 0 ;
void DealMessage(const MSG &msg);
unsigned int static __stdcall MsgCtrlProc(VOID* param);
int _tmain(int argc, _TCHAR* argv[])
{
PROCESS_INFORMATION pi;
STARTUPINFO si;
memset(&pi, 0, sizeof(PROCESS_INFORMATION));
memset(&si, 0, sizeof(STARTUPINFO));
wchar_t wszExePath[MAX_PATH] = L"F:\\CPPtest\\sdta\\Debug\\ChildProc.exe"; //子进程路径
if(FALSE == CreateProcess(wszExePath, NULL, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi))
{
return 0;
}
_beginthreadex(NULL, 0, MsgCtrlProc, NULL, 0, &g_dwControlThread); //创建线程
while (1)
{
wscanf(L"%c", &g_wcControl); //线程中不能有printf之类的函数,所以在进程中处理
fflush(stdin);
Sleep(100);
if (g_wcControl >= L'a' && g_wcControl <= L'z')
{
::PostThreadMessage(g_dwControlThread, MS_OPENFINISHED, g_wcControl, 0); //向本进程的线程发送消息
}
else if (g_wcControl >= L'0' && g_wcControl <= L'9')
{
::PostThreadMessage(pi.dwThreadId, MS_RUN, (WPARAM)g_dwControlThread, 0); //向子进程发送消息
}
}
return 0;
}
unsigned int static __stdcall MsgCtrlProc(VOID* param)
{
BOOL bRet = TRUE;
MSG msg;
while ((bRet = ::GetMessage(&msg, NULL, 0, 0)) != 0)
{
if (bRet == -1)
{
continue;
}
else
{
DealMessage(msg);
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}
return (int)msg.wParam;
}
void DealMessage(const MSG &msg)
{
switch (msg.message)
{
case MS_OPENFINISHED:
{
::MessageBox(NULL, L"控制主进程", L"控制主进程", MB_OK);
}
break;
case MS_RETURN:
{
::MessageBox(NULL, L"Return", L"Return", MB_OK); //子进程发回的消息
}
}
}
ChildProc.cpp
#include <Windows.h>
#include <process.h>
UINT g_dwControlThread = 0 ;
UINT g_dwMainThread = 0;
const UINT MS_OPENFINISHED = WM_USER+8001;
const UINT MS_RUN = MS_OPENFINISHED + 1;
const UINT MS_RETURN = MS_RUN + 1;
int _tmain(int argc, _TCHAR* argv[])
{
g_dwMainThread = ::GetCurrentThreadId(); //在MainProc那个主进程中用这个获得线程也行,用_beginthreadex是为了程序好控制
::MessageBox(NULL, L"受控进程22222", L"受控进程22222", MB_OK); //测试用
BOOL bRet = TRUE;
MSG msg;
while ((bRet = ::GetMessage(&msg, NULL, 0, 0)) != 0)
{
if (bRet == -1)
{
continue;
}
else
{
switch (msg.message)
{
case MS_RUN:
{
::MessageBox(NULL, L"受控进程", L"受控进程", MB_OK);
::PostThreadMessage((DWORD)msg.wParam, MS_RETURN, 0, 0);//接收到主进程的消息,并向主进程发送消息
}
}
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}
return (int)msg.wParam;
}
#26
windows核心编程里面好象有讲的。
#27
为了得分,我不得不说我们关于进程间通讯(ipc)的一点经验。
第一:使用socket通讯,效率高,实用范围大。
第二:推荐使用ascii码通讯。
第三:服务器数据缓冲的处理,先进先出。
第四:处理粘包。
第五:登陆连接,*下线或者重连机制。
第六:使用线程池处理大量服务并行机制。
第七:。。。。。
第八:。。。。。。
第一:使用socket通讯,效率高,实用范围大。
第二:推荐使用ascii码通讯。
第三:服务器数据缓冲的处理,先进先出。
第四:处理粘包。
第五:登陆连接,*下线或者重连机制。
第六:使用线程池处理大量服务并行机制。
第七:。。。。。
第八:。。。。。。
#1
有没有其他线程或者进程reset hEvent_exit
CEvent::SetEvent
BOOL SetEvent();
返回值:如果操作成功,则返回非零值,否则为0。
说明:
设置事件的状态为有标记,释放任意等待线程。如果事件是手工的,此事件将保持有标记直到调用 ResetEvent。这种情况下将释放多个线程,如果事件是自动的,此事件将保持有标记,直到一个线程被释放,系统将设置事件的状态为无标记。如果没有线程在等待,则此事件将保持有标记,直到一个线程被释放。
CEvent::SetEvent
BOOL SetEvent();
返回值:如果操作成功,则返回非零值,否则为0。
说明:
设置事件的状态为有标记,释放任意等待线程。如果事件是手工的,此事件将保持有标记直到调用 ResetEvent。这种情况下将释放多个线程,如果事件是自动的,此事件将保持有标记,直到一个线程被释放,系统将设置事件的状态为无标记。如果没有线程在等待,则此事件将保持有标记,直到一个线程被释放。
#2
问题解决。 散分了,来人给分,晚上结贴
#3
GX .
#4
我是进来学习的。
#5
JF...
#6
我来接分
#7
来接分了
#8
顺便说下你的问题所在,解决办法是什么
#9
来接分了
#10
来接分了
#11
咋解决的啊。。。
#12
UP~~~
#13
楼主也不说说是怎么回事哦。。。
让我过下瘾吧。
让我过下瘾吧。
#14
问题确实被解决了,但是仍然存在困惑,高人可以解答下
1:使用命名句柄方法,A 进程创建 通信句柄时候去掉权限的限制,如下CreateEvent第一个参数为NULL
进程B 使用createEvent “创建”同样命名的句柄
这个时候通信成功了,比较疑惑,如果我使用OPenEvent 打开句柄就不行,getlasterror 提示为0;
以上是我现在使用的解决方案,不过命名换成了不冲突的,是一个初级解决方案。
1:使用命名句柄方法,A 进程创建 通信句柄时候去掉权限的限制,如下CreateEvent第一个参数为NULL
HANDLE hExitEvent = ::CreateEvent(NULL,false,false,TEXT("_hExitEvent"));
HANDLE husedEvent = ::CreateEvent(NULL,false,false,TEXT("_hUsedEvent"));
STARTUPINFO si;
ZeroMemory(&si,sizeof(si));
si.cb=sizeof(STARTUPINFO);
PROCESS_INFORMATION pi;
if(!CreateProcess(NULL,TEXT("ChildProcess.exe"),NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
{
cout<<"failed to run chilld process"<<endl;
}
::SetEvent(husedEvent);
cout<<"send message to parent!" <<endl;
Sleep(100);
::WaitForSingleObject(hExitEvent,INFINITE);
cout<<"Answered by other process!\n";
system("PAUSE");
return 0;
进程B 使用createEvent “创建”同样命名的句柄
HANDLE hExitEvent = ::CreateEvent(NULL,false,false,TEXT("_hExitEvent"));
if(::GetLastError() ==ERROR_ALREADY_EXISTS )
{
cout<<"HANDLE is created by another process\n";
}
HANDLE husedEvent = ::CreateEvent(NULL,false,false,TEXT("_hUsedEvent"));
::WaitForSingleObject(husedEvent,INFINITE);
cout<<"recive the message from parent!"<<endl;
SetEvent(hExitEvent);
Sleep(50);
return 0;
这个时候通信成功了,比较疑惑,如果我使用OPenEvent 打开句柄就不行,getlasterror 提示为0;
以上是我现在使用的解决方案,不过命名换成了不冲突的,是一个初级解决方案。
#15
第2个解决方案比较简单
通过继承句柄来通信的。
我大致说下
CreateEvent()的第一个参数初始化一下。并传入,
然后在进程A中(父进程)创建子进程时候选择可以继承,并且在cmdline 中传入事件的内核地址
进程B中,解析Argv[1],解释成一个地址,赋给一个HANDLE,setEvent 这个handle通知进程A退出
这个方法虽然能通信,但是太失败。。。
通过继承句柄来通信的。
我大致说下
CreateEvent()的第一个参数初始化一下。并传入,
然后在进程A中(父进程)创建子进程时候选择可以继承,并且在cmdline 中传入事件的内核地址
进程B中,解析Argv[1],解释成一个地址,赋给一个HANDLE,setEvent 这个handle通知进程A退出
这个方法虽然能通信,但是太失败。。。
#16
设置权限的话,进程B应该打开某些权限吧。
顺便接分。
顺便接分。
#17
没考虑用PossthreadMessage ?
#18
我OPenEvent设置的是那个sync(线程同步类的)权限。GetLastError 提示 为0 ,这时候就跟我帖子的问题一样了,B退出了,A始终在等待。说明B收到了消息,但是,A没收到?
#19
铅哥,说的高级了。我菜的很。吃饭回来试试。米饭去了先
#20
这个好用,不高级的。用几用就熟悉了,要不要我写段代码来测试。。。
#21
接分了!呵呵
#22
哈哈,我先试试。我先探探MSDN
#23
那好的,呵呵
#24
我帮你写了个简单的程序,大致是:
在主进程中创建一个子进程和一个线程,线程里处理消息本进程的消息和子进程返回的消息。
PossThreadMessage, 函数的的最后两个参数可以用作想要传递的数据。
在主进程中创建一个子进程和一个线程,线程里处理消息本进程的消息和子进程返回的消息。
PossThreadMessage, 函数的的最后两个参数可以用作想要传递的数据。
#25
MainProc.cpp
ChildProc.cpp
#include <Windows.h>
#include <process.h>
const UINT MS_OPENFINISHED = WM_USER+8001;
const UINT MS_RUN = MS_OPENFINISHED + 1; //子进程的消息
const UINT MS_RETURN = MS_RUN + 1;
wchar_t g_wcControl = L'\0';
unsigned int g_dwControlThread = 0 ;
void DealMessage(const MSG &msg);
unsigned int static __stdcall MsgCtrlProc(VOID* param);
int _tmain(int argc, _TCHAR* argv[])
{
PROCESS_INFORMATION pi;
STARTUPINFO si;
memset(&pi, 0, sizeof(PROCESS_INFORMATION));
memset(&si, 0, sizeof(STARTUPINFO));
wchar_t wszExePath[MAX_PATH] = L"F:\\CPPtest\\sdta\\Debug\\ChildProc.exe"; //子进程路径
if(FALSE == CreateProcess(wszExePath, NULL, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi))
{
return 0;
}
_beginthreadex(NULL, 0, MsgCtrlProc, NULL, 0, &g_dwControlThread); //创建线程
while (1)
{
wscanf(L"%c", &g_wcControl); //线程中不能有printf之类的函数,所以在进程中处理
fflush(stdin);
Sleep(100);
if (g_wcControl >= L'a' && g_wcControl <= L'z')
{
::PostThreadMessage(g_dwControlThread, MS_OPENFINISHED, g_wcControl, 0); //向本进程的线程发送消息
}
else if (g_wcControl >= L'0' && g_wcControl <= L'9')
{
::PostThreadMessage(pi.dwThreadId, MS_RUN, (WPARAM)g_dwControlThread, 0); //向子进程发送消息
}
}
return 0;
}
unsigned int static __stdcall MsgCtrlProc(VOID* param)
{
BOOL bRet = TRUE;
MSG msg;
while ((bRet = ::GetMessage(&msg, NULL, 0, 0)) != 0)
{
if (bRet == -1)
{
continue;
}
else
{
DealMessage(msg);
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}
return (int)msg.wParam;
}
void DealMessage(const MSG &msg)
{
switch (msg.message)
{
case MS_OPENFINISHED:
{
::MessageBox(NULL, L"控制主进程", L"控制主进程", MB_OK);
}
break;
case MS_RETURN:
{
::MessageBox(NULL, L"Return", L"Return", MB_OK); //子进程发回的消息
}
}
}
ChildProc.cpp
#include <Windows.h>
#include <process.h>
UINT g_dwControlThread = 0 ;
UINT g_dwMainThread = 0;
const UINT MS_OPENFINISHED = WM_USER+8001;
const UINT MS_RUN = MS_OPENFINISHED + 1;
const UINT MS_RETURN = MS_RUN + 1;
int _tmain(int argc, _TCHAR* argv[])
{
g_dwMainThread = ::GetCurrentThreadId(); //在MainProc那个主进程中用这个获得线程也行,用_beginthreadex是为了程序好控制
::MessageBox(NULL, L"受控进程22222", L"受控进程22222", MB_OK); //测试用
BOOL bRet = TRUE;
MSG msg;
while ((bRet = ::GetMessage(&msg, NULL, 0, 0)) != 0)
{
if (bRet == -1)
{
continue;
}
else
{
switch (msg.message)
{
case MS_RUN:
{
::MessageBox(NULL, L"受控进程", L"受控进程", MB_OK);
::PostThreadMessage((DWORD)msg.wParam, MS_RETURN, 0, 0);//接收到主进程的消息,并向主进程发送消息
}
}
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}
return (int)msg.wParam;
}
#26
windows核心编程里面好象有讲的。
#27
为了得分,我不得不说我们关于进程间通讯(ipc)的一点经验。
第一:使用socket通讯,效率高,实用范围大。
第二:推荐使用ascii码通讯。
第三:服务器数据缓冲的处理,先进先出。
第四:处理粘包。
第五:登陆连接,*下线或者重连机制。
第六:使用线程池处理大量服务并行机制。
第七:。。。。。
第八:。。。。。。
第一:使用socket通讯,效率高,实用范围大。
第二:推荐使用ascii码通讯。
第三:服务器数据缓冲的处理,先进先出。
第四:处理粘包。
第五:登陆连接,*下线或者重连机制。
第六:使用线程池处理大量服务并行机制。
第七:。。。。。
第八:。。。。。。