如何让程序等待

yeiliuxing 2002-10-05 09:40:38
如何让程序等待,而又不占用系统资源
并且,我们可以以消息触发,使系统继
续运行,就像状态栏中的程序一样,像
死了一样不占用系统,而且又能监听自
己的消息。就比方说,我想用csocket
类实现,像qq一样的功能可以吗?
我开始想用无限循环,来反复监测一个
数据成员的状态。但我认为好像会造成
资源浪费。而用ontime定时监测,如果
时间短了一样是浪费资源,时间长了
就达不到实时性了。不知道windows的
消息循环是怎么实现的,不知哪路高人
能帮我解决这个问题?
谢谢!!
...全文
440 39 打赏 收藏 转发到动态 举报
写回复
用AI写文章
39 条回复
切换为时间正序
请发表友善的回复…
发表回复
HelloWorld 2002-10-16
  • 打赏
  • 举报
回复
如果只是想用CSocket解决Socket问题,用CSocket本身的机制就可以了。如果想自定义等待机制,用WaitForSingleObject(),不过你需要懂一些多线程的知识。最好看一下候捷翻译的《Win32 多线程程序设计》,讲的很明白。简单的说就是你在主线程生成一个event,启动你的work线程,主线程等待。在Work线程你作自己的处理,如果要激活主线程,就setevent(),主线程激活,可以结束整个进程或者作另外的处理。
liuyup 2002-10-16
  • 打赏
  • 举报
回复
gz
yaotang 2002-10-15
  • 打赏
  • 举报
回复
皆摘自www.vckbase.com;你的帖子好热闹
所以我也来凑凑热闹 :-)
yaotang 2002-10-15
  • 打赏
  • 举报
回复
我们在开发是经常需要在启动一个进程之后等待其结束后再继续运行。

在这里提供了一个名为Wait的函数,它会为你完成上面的功能。实现的思想是在启动进程后等待其结束,由于进程是一种资源,而资源的句柄在WIN32中可以作为核心量使用。你可以使用WaitForSingleObject等待核心量状态改变为有信号状态。对进程来讲当进程结束时其状态转变为有信号。

在本例中使用了一个单独的线程来启动进程并等待结束。

Wait()
BOOL Wait(CString szCmdLine)
{
LPTHREADINFO pThreadInfo = new THREADINFO;
CEvent *pThreadEvent = new CEvent(FALSE, TRUE);
ASSERT_VALID(pThreadEvent);
if(pThreadInfo)
{
pThreadInfo->pTermThreadEvent = pThreadEvent;
pThreadInfo->strPathName = szCmdLine;

AfxBeginThread(LaunchAndWait, pThreadInfo);
WaitForSingleObject(pThreadEvent->m_hObject, INFINITE);
return TRUE;
}
return FALSE;
}

LaunchAndWait()
UINT LaunchAndWait(LPVOID pParam)
{
LPTHREADINFO pThreadInfo = (LPTHREADINFO) pParam;
PROCESS_INFORMATION stProcessInfo;
if(LaunchApplication(pThreadInfo->strPathName, &stProcessInfo))
{
HANDLE hThreads[2];
hThreads[0] = pThreadInfo->pTermThreadEvent->m_hObject;
hThreads[1] = stProcessInfo.hProcess;
DWORD dwIndex = WaitForMultipleObjects(2, hThreads, FALSE, INFINITE);
CloseHandle(stProcessInfo.hThread);
CloseHandle(stProcessInfo.hProcess);
pThreadInfo->pTermThreadEvent->SetEvent();
if(pThreadInfo)
delete pThreadInfo;
}
else
pThreadInfo->pTermThreadEvent->SetEvent();
return 0;
}


LaunchApplication()
BOOL LaunchApplication(LPCTSTR pCmdLine, PROCESS_INFORMATION *pProcessInfo)
{
STARTUPINFO stStartUpInfo;

memset(&stStartUpInfo, 0, sizeof(STARTUPINFO));

stStartUpInfo.cb = sizeof(STARTUPINFO);

stStartUpInfo.dwFlags = STARTF_USESHOWWINDOW;
stStartUpInfo.wShowWindow = SW_SHOWDEFAULT;

return CreateProcess(NULL, (LPTSTR)pCmdLine, NULL, NULL, FALSE,
NORMAL_PRIORITY_CLASS, NULL,
NULL, &stStartUpInfo, pProcessInfo);
}




yaotang 2002-10-15
  • 打赏
  • 举报
回复
主要运用ReadFile()与WriteFile()API函数,若为异步通信方式,两函数中最后一个参数为指向OVERLAPPED结构的非空指针,在读写函数返回值为FALSE的情况下,调用GetLastError()函数,返回值为ERROR_IO_PENDING,表明I/O操作悬挂,即操作转入后台继续执行。此时,可以用WaitForSingleObject()来等待结束信号并设置最长等待时间,举例如下:

BOOL bReadStatus;
bReadStatus = ReadFile( m_hIDComDev, buffer,
dwBytesRead, &dwBytesRead, &m_OverlappedRead );
if(!bReadStatus)
{
if(GetLastError()==ERROR_IO_PENDING)
{
WaitForSingleObject(m_OverlappedRead.hEvent,1000);
return ((int)dwBytesRead);
}
return(0);
}
return ((int)dwBytesRead);

---- 定义全局变量m_Serial作为新建通信类CSimpleComm的对象,通过调用类的成员函数即可实现所需串行通信功能。与方法一相比,方法二赋予串行通信程序设计较大的灵活性,端口的读写可选择较简单的查询式,或通过设置与外设数据发送时间间隔TimeCycle相同的定时器:SetTimer(1,TimeCycle,NULL),进行定时读取或发送。

CSampleView:: OnTimer(UINT nIDEvent)
{
char InputData[30];
m_Serial.ReadData(InputData,30);
// 数据处理
}
---- 若对端口数据的响应时间要求较严格,可采用事件驱动I/O读写,Windows定义了9种串口通信事件,较常用的有:

---- EV_RXCHAR: 接收到一个字节,并放入输入缓冲区。

---- EV_TXEMPTY: 输出缓冲区中的最后一个字符发送出去。

---- EV_RXFLAG: 接收到事件字符(DCB结构中EvtChar成员),放入输入缓冲区。

---- 在用SetCommMask()指定了有用的事件后,应用程序可调用WaitCommEvent()来等待事件的发生。SetCommMask(hComm,0)可使WaitCommEvent()中止。

tcice 2002-10-15
  • 打赏
  • 举报
回复
老兄的烦恼我觉得如果对select了解的话,应该不存在什么问题,等待是否有socket的消息就可以来触发,select等待不知道暂不暂用系统资源?这个问题
我没有研究过,如果哪位老兄研究过,请告之!
clin2y 2002-10-15
  • 打赏
  • 举报
回复
gz
as2001 2002-10-15
  • 打赏
  • 举报
回复
用钩子就可以了
CharmDream 2002-10-15
  • 打赏
  • 举报
回复
gz
qrlvls 2002-10-13
  • 打赏
  • 举报
回复
准确的说,那是不可能的,你要判断消息就不可能不占用资源
yeiliuxing 2002-10-13
  • 打赏
  • 举报
回复
非常感谢众位兄弟的热心帮忙
在苦思多日后,我来发表一下近日的心得
首先,让我们来看一下终日困扰我们的getmessage
在这里,我们对peekmessage表示放弃,因为正如西山月所言
peekmessage无论是否有消息到达都立即返回,程序并不会交出控制权。
所以,peekmessage达不到我们要求的阻塞效果。
至于getmessage,我们都知道windows本身就是消息驱动的。而这个消息驱动
正是利用getmessage(或者也可以用peekmessage ,因为getmessage和peekmessage

实际在内部是调用同样的核心代码段的。他们的主要区别是getmessage在没有消

息的时候让线程休眠而peekmessage不会)来检测消息并
把消息发送给wndproc由wndproc来检测哪一条消息该处理该如何处理。
getmessage只是让我们在桌这件事情的同时可以继续监听消息,而问题来了
getmessage并不只监听我们想要的消息,而是只要他发现有消息请求就会停
止阻塞。windows程序中把getmessage用在主线程中因为在没有消息到来时
他不必做任何事情。而这一功能mfc已经帮我们隐藏在框架内部了。如果我们
要做一个基于getmessage的多线程,那我建议使用peekmessage因为
peekmessage不会出现不必要的阻塞。
所以,getmessage也达不到我们要求的等待。我们所要求的是当我们需要的
事件发生时我们的程序可以继续运行处理这个事件。
因为我的无知才产生了这个问题,而现在这个问题转化了。现在的问题是我们
如何来在我们想的时候发送这个事件,在这个事件到达时我们如何捕获他?
其次,讲到sleep,sleep是我们第一个否决的方法,因为我们不知道该休息多
长时间。这个问题不需要多说,大家都会了解。
再次,是waitforsingleobject,waitformultipleobjects我是在线程同步中找
到他们的说明的,waitforsingleobject是等待一个事件的发生,这个"事件"
是一个对象,他有两种状态:发生和没发生。当线程运行到这里时

waitforsingleobject会等待为他指定的事件发生,他会在制定事件到来时返
回或者在指定的超时时间后返回。而在另一个线程中我们在想要继续执行时将
事件设置为发生来触发事件激活等待事件的线程。
对于waitformultipleobject我还是有些不理解,他等待一个或多个对象变成

singled.如果我指定了多个对象,那么是等到其中一个变成singled还是全部
呢?对于msgwaitformultipleobject我还需要多看些资料才能了解他的参数。
对于这组函数,完成我们需要的问题是没什么问题了,但是我在考虑它的可
移植性,和是否还有更简单的方法。
最后,让我们来回顾一下立冬所提出的使用csocket类的消息处理函数,也就是
西山月后来指出的
"WSAAsyncSelect函数是登记一个SOCKET事件,可以是以下几个事件之一如,

Read,Write,Connet,Accept,Close等,几乎是包含了所有的套接口事件,当登
记的事件到达时,就会向指定的窗口发送一个消息,这样程序就能作出相应的
反应。"
从一开始我就考虑用消息这也是我要考虑的更简单的方法,但我因如何得到

socket的消息而困惑。冬子曾为我指出从csocket类派生一个新类,在派生类中
捕获基类的Read,Write,Connet,Accept,Close等我们需要的消息,然后向主窗
口发送自定消息来实现对事件的响应。但我对自定消息不是很理解,而且是否
不用构造新类就能捕获需要的消息呢?
对以上的不解还请各位慷慨解囊,谢谢!!
ancienttale 2002-10-12
  • 打赏
  • 举报
回复
又要等待,又要收消息,可以用函数
MsgWaitForMultipleObjects
蓝天 2002-10-12
  • 打赏
  • 举报
回复
!
天限天空 2002-10-12
  • 打赏
  • 举报
回复
up
goodlcp 2002-10-12
  • 打赏
  • 举报
回复
可以用自定义消息,我做过类似的程序。
程序A空闲等待,程序B发生了一事件后,向程序A发送一自定义消息。
程序A接到此自定义消息,并处理此消息。
yeiliuxing 2002-10-11
  • 打赏
  • 举报
回复
是吗?
谢谢!!
我试试,不过我还是希望有人把它贴出来。
不懂得人也许不只我一个,我不喜欢看别人的贴字的时候一到关键问题时
就见到email或者转到别处了
frued 2002-10-11
  • 打赏
  • 举报
回复
呵呵,学习,多谢
禽兽v5 2002-10-10
  • 打赏
  • 举报
回复
可以参考

〈Win32 多线程程序设计〉

〈Windows 核心编程〉

〈Windows 高级编程指南 3th〉

可以去www.china-pub.com查找相关资料
YoungBoz 2002-10-10
  • 打赏
  • 举报
回复
另外教你一个方法,你如对某个函数不明了,而又看不懂英文的MSDN的话不妨把它放到google,或者Sohu的搜索引擎中,一般就能找到它的有关资料了,还能找到相关的例程。对这一招我是屡试不爽
YoungBoz 2002-10-10
  • 打赏
  • 举报
回复
只所以采用GetMessage是因为这个函数能在没有消息到达时起到释放控制权的作用,用一个线程中的词来描述的话,就是阻塞了线程,面PeekMessage无论是否有消息到达都立即返回,程序并不会交出控制权。这个函数只在我不想交出控制权,但需要查询有无消息时才使用,如果想让程序等待那还是要用GetMessage;在MSDN中对两个函数的说明中对PeekMessage用Check(检查)一词,而对GetMessage用的是retrieve(寻回)可知两者的区别。WSAAsyncSelect函数是登记一个SOCKET事件,可以是以下几个事件之一如,Read,Write,Connet,Accept,Close等,几乎是包含了所有的套接口事件,当登记的事件到达时,就会向指定的窗口发送一个消息,这样程序就能作出相应的反应。
加载更多回复(19)

16,467

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧