tag 标签: 阻塞

相关博文
  • 热度 22
    2015-3-24 13:44
    2115 次阅读|
    0 个评论
       EDN博客精华文章   作者: tanghtctc 混合使用阻塞/非阻塞语句   verilog语言的一个难点就是阻塞语句和非阻塞语句。一般来说,always语句块中如果对组合逻辑建模,敏感事件为电平触发,并且使用阻塞赋值语句;对时序逻辑建模,敏感时间为沿触发,并且使用非阻塞语句。   深入的说,   对于阻塞语句,其综合出的组合逻辑输出,被馈送到其后引用它的语句的   组合逻辑的输入端,也即后面的语句引用其新值。   对于非阻塞语句,其综合出的触发器输出,被馈送到其后引用它的语句的   组合逻辑的输入端,也即后面的语句引用其旧值。   不管是阻塞赋值还是非阻塞赋值语句,若在该句之前对其值(除纯粹的临时变量)进行引用,则只能引用其上个时钟周期赋予的旧值。   在边沿敏感周期行为always顺序块中使用阻塞、非阻塞赋值语句,只对其后引用其值的语句产生影响。   在边沿敏感的周期行为always语句块中,若变量被某条语句引用上个时钟周期赋的值(旧值),则该变量综合出的触发器的输出端被馈送到引用它的语句的输入端;若该变量被某条语句引用当前时钟周期赋的值(新值),则该变量综合出的组合逻辑的输出端被馈送到引用它的语句的输入端。   下面有几段类似的代码,在Quartus得到RTL结果,就可以对这两种语句有一些感觉了,不过我不推荐这样的混合写法,一方面容易出错,另一方面,不容易把握硬件结果,会使Verilog代码风格走向软件。这些代码权当学习使用啦!
  • 热度 29
    2013-5-1 16:22
    4494 次阅读|
    1 个评论
    by Yuanzhong Deng RFStory.com已经改为 MiniIC.com 一大一小两个信号,大信号功率远大于小信号功率(例如大10dB或更多)。 两个信号同时输入放大器,由于器件的非线性特性,两个信号的增益将不同(大信号增益大于小信号增益),即常说的”大压小“现象。这是影响接收机阻塞性能的重要因素。 ”大压小“现象的原理何在呢?如何定量衡量”大压小“特性呢? 我们用多项式模型来描述放大器的非线性:   式中a1与a3符号相反,a1为小信号线性增益,a3产生增益压缩。 输出基频信号的幅度为: 由于非线性导致的增益压缩量为C:   当输入信号同时包含小信号 V 1 cos( w 1 t)和 大信号 V 2 cos(w 2 t) 时:   式中a1与a3符号相反,当V 2 (大信号的幅度)增加时,小信号的增益将减小。 小信号的增益压缩量:   从下图可以看到,小信号压缩量(纵轴)随大信号压缩量(横轴)增长呈指数增长:   因此,在进行接收机设计时,要求接收链路各级器件对大信号有足够的回退量,以保证接收机的阻塞性能。   本文为原创文章,转载请注明:转载自 射频那些事儿  。
  • 热度 21
    2013-2-14 16:41
    1970 次阅读|
    0 个评论
         这里有一个数组:Data 、Data 、Data 和Data ,它们都是4比特的数据。我们需要在它们当中找到一个最小的数据,同时将该数据的索引输出到LidMin中,这个算法有点类似于“冒泡排序”的过程,而且需要在一个时钟周期内完成。例如,如果这4个数据中 Data 最小,那么LidMin的值则为2。    module Bubble_Up(                     Rst_n,                     Clk,                     Data,                     Lid_Min                     );     input Rst_n;     input Clk;     input   Data  ;     output   Lid_Min;     reg   Lid_Min;      always @(posedge Clk or negedge Rst_n)     begin         if (~Rst_n)         begin              Lid_Min = 2'd0;         end         else            begin                if (Data  = Data )    //"="表示小于等于                begin                    Lid_Min = 2'd0;    //"="表示非阻塞赋值                end                if (Data  = Data )                begin                    Lid_Min = 2'd1;                end                                          if (Data  = Data )                 begin                     Lid_Min = 2'd2;                 end                 if (Data  = Data )                 begin                     Lid_Min = 2'd3;                 end             end         end     endmodule   我们的原意是首先将Lid_Min设置为一个初始值(任意值都可以),然后将Data ~Data 与Data 进行比较,每比较一个数,就将较小的索引暂存在Lid_Min中,然后再进行下一次比较。当4组数据比较完成之后,最小的数据索引就会保留在Lid_Min 中。   我们在以上代码中使用了非阻塞赋值,结果发现,仿真波形根本不是我们所需要的功能,如图所示,图中的Data ~Data 分别为 11、3、10和12,Lid_Min的初始值为0。按道理来说,Lid_Min的计算结果应该为1,因为Data 最小,但仿真波形却为2。 为什么会得出这样的结果呢?   在时钟上升沿到来以后,且Rst_n信号无效时开始执行以下4个语句,假设这时候的Lid_Min是0,Data ~Data 分别为11、3、10和12:              if (Data  = Data )    //"="表示小于等于               begin                    Lid_Min = 2'd0;    //"="表示非阻塞赋值                end                if (Data  = Data )                begin                    Lid_Min = 2'd1;                end                                          if (Data  = Data )                 begin                     Lid_Min = 2'd2;                 end                 if (Data  = Data )                 begin                     Lid_Min = 2'd3;                 end   第一句的if为真,因此执行Lid_Min = 2’d0,而这时候,Lid_Min并没有立刻被赋值,而是调度到事件队列中等待执行,这是非阻塞赋值的特点。   第二句的if为真,因此执行Lid_Min = 2’d1,这是Lid_Min也没有立刻被赋值为1,而是调度到事件队列中等待执行。当前的Lid_Min还是0,没有发生任何变化。   同样,第三句的if也为真,因此执行Lid_Min = 2’d2,将更新事件调度到事件队列中等待执行。当前的Lid_Min还是0。   而第四句的if为假,因此直接跳过Lid_Min = 2’d3,这时跳出always语句,等待下一个时钟上升沿。   在以上的always语句执行完成以后,仿真时间没有前进。这时存在于事件队列中当前仿真时间上的3个被调度的非阻塞更新事件开始执行,它们分别将Lid_Min更新为0、1和2。   按照Verilog语言的规范,这3个更新事件属于同一仿真时间内的事件,它们之间的执行顺序随机,这就产生了不确定性。一般的仿真器在实现的时候是根据它们被调度的先后顺序执行的,事件队列就像一个存放事件的FIFO,它是分层事件队列的一部分,如图所示:   这3个事件在同一仿真时间被一一执行,而真正起作用的时最后一个更新事件,因此在仿真的时候得到的最终结果时Lid_Min为2。   然后我们想要得到的结果是,在每个if语句判断并执行完成以后,Lid_Min先暂存这个中间值,再进行下一次比较,也就是说在进行下一次比较之前,这个Lid_Min必须被更新,而这一点也正是阻塞赋值的特点,因此我们将代码作如下更改:     module Bubble_Up(                     Rst_n,                     Clk,                     Data,                     Lid_Min                     );     input Rst_n;     input Clk;     input   Data  ;     output   Lid_Min;     reg   Lid_Min;      always @(posedge Clk or negedge Rst_n)     begin         if (~Rst_n)         begin              Lid_Min = 2'd0;         end         else            begin                if (Data  = Data )    //"="表示小于等于                begin                    Lid_Min = 2'd0;    //"="表示非阻塞赋值                end                if (Data  = Data )                begin                    Lid_Min = 2'd1;                end                                          if (Data  = Data )                 begin                     Lid_Min = 2'd2;                 end                 if (Data  = Data )                 begin                     Lid_Min = 2'd3;                 end             end         end     endmodule   其仿真波形如图所示:   在代码仿真过程中,第二句的if为真,执行Lid_Min = 2'd1,根据阻塞赋值的特点,Lid_Min被立刻赋值为1。在执行第三句if的时候,if (Data  = Data )为假,直接跳过Lid_Min = 2'd2不执行,同样也跳过Lid_Min = 2'd3不执行。Lid_Min被最终赋值为1,这正是我们想要的结果。         另外,为了使代码看起来更简洁,我们使用for语句改写了代码:      module Bubble_Up(                      Rst_n,                      Clk,                      Data,                      Lid_Min                      );       input Rst_n;       input Clk;       input   Data  ;       output   Lid_Min;       reg   Lid_Min;       integer i;       always @(posedge Clk or negedge Rst_n)       begin           if (~Rst_n)           begin               Lid_Min = 2'd0;           end           else           begin               for (i = 2'd0; i = 2'd3; i = i + 2'd1)               begin                   if (Data  = Data )                   begin                         Lid_Min = i;                   end               end           end        end      endmodule   这种写法与前面展开的写法完全等效,功能完全一致。今后大家在读代码时发现带有for语句的电路功能比较难理解,可以将这些语句展开,增强代码的可读性。  
  • 热度 19
    2012-7-6 16:05
    9304 次阅读|
    0 个评论
    VC编程Windows消息处理机制、阻塞试验、SetTimer、MessageBox、小心消息响应处理函数多个并存 wxleasyland@sina.com 2012.7   wxleasyland试验:   VC6标准WIN32程序,Windows消息处理机制: 1.在注册窗口类时,指定了消息处理函数WndProc()。 2.WinMain()里有消息循环:     while (GetMessage(msg, NULL, 0, 0))     {        if (!TranslateAccelerator(msg.hwnd, hAccelTable, msg))        {            TranslateMessage(msg);            DispatchMessage(msg);        }     } 3.在WndProc()里,对各个消息进行处理!!     消息队列是线程所有,并非窗口所有和进程所有。 一个线程的所有窗口,比如父窗口(主窗口)、对话框、消息框等都是使用这个线程的同一个消息队列!!!! 窗口有消息循环。窗口里的控件应该就没有消息循环了吧。   试验: 一、MFC中,用TIMER,发现,在TIMER响应函数中,用MessageBox(),则会不断地出现MessageBox。 而且当前响应函数会停止在MessageBox上,直到MessageBox返回才继续执行后面的语句!   用SendMessage或PostMessage来试消息响应,也是一样:响应函数中有MessageBox(),则会出现多个MessageBox。   说明MessageBox阻塞了函数,却没有阻塞消息分发。     二、VC建WIN32程序(标准HELLO WORLD),试验发现,如果WndProc()里有MessageBox,当前的WndProc()会暂时停止在MessageBox,直到MessageBox返回才继续执行后面的语句!! 如果MessageBox出现,这时一个WM_PAINT出现了,则会执行一个新的WndProc()。即WndProc()并行出现了!!线程只有一个,但WndProc()可以出现多个! 用ABOUT对话框代替MessageBox,情况也是一样!ABOUT对话框出现时,父窗口(即主程序)点不出来,但父窗口WM_PAINT能正常运行!!! 即像别的文章说的, 对话框和消息框会有自己的消息循环,但线程是同一个线程,所以线程的所有消息会被分发处理。     三、再试下面程序, void CUnicodewcharDlg::OnButton4() {     SendMessage(UM_SOCK);      // UM_SOCK为自定义消息,已经和OnRecv相关联 }   BOOL running=FALSE;   void CUnicodewcharDlg::OnRecv() {     if (running==TRUE) {::MessageBox(NULL,"ERROR","",MB_OK); return;}     running=TRUE;     ::MessageBox(NULL,"OK","",MB_OK); ::MessageBox(NULL,"返回","",MB_OK);     running=FALSE; }   发现,按OnButton4后,先出现一个"OK"消息框,再点OnButton4,就出现"ERROR"消息框。 如果"OK"消息框关闭了,则不会出现"返回"消息框,再点OnButton4,仍是出现"ERROR"消息框!!!!!!! 一定要"ERROR"消息框和"OK"消息框都关闭了,才会出现"返回"消息框,再点OnButton4,才会出现"OK"消息框!!   说明是: 父窗消息循环,调用消息响应函数生成了第一个消息框,同时父窗调用的消息响应函数阻塞,父窗消息循环阻塞;第一个消息框开始接手负责消息循环(是自己有消息循环还是把父窗的消息循环重入了继续使用?)。 第一个消息框消息循环,调用消息响应函数生成了第二个消息框,同时第一个消息框调用的消息响应函数阻塞,第一个消息框消息循环阻塞;第二个消息框开始接手负责消息循环(是自己有消息循环还是把父窗的消息循环重入了继续使用?)。 第二个消息框消息循环。。。 即:父窗阻塞-第一个消息框阻塞-第二个消息框 如果第一个消息框关闭,但第二个消息框未关闭,则第一个消息框调用的消息响应函数仍在阻塞中,故父窗调用的消息响应函数也在阻塞中,所以继续运行不下去,而第二个消息框仍在进行消息循环。只有第二个消息框关闭了,第一个消息框调用的消息响应函数才会继续运行并返回,然后父窗调用的消息响应函数才会继续运行并返回!!!   第二个消息框消息循环,收到父窗WM_PAINT,调用父窗消息响应函数,WM_PAINT这一部分如果没有阻塞,则消息响应函数可以马上返回。再进行下一个消息处理。所以父窗不会因为没有刷新而失去显示,否则就显示不正常了。   消息响应函数可以同时多次进入 ,比如父窗调用了阻塞了,第一个消息框又调用了阻塞了,第二个消息框又调用了。。。       三、试验子窗口是自己有消息循环还是把父窗的消息循环重入了继续使用? 用WIN32(标准HELLO WORLD)程序来试:   在WinMain()中:     while (GetMessage(msg, NULL, 0, 0))     {        if (!TranslateAccelerator(msg.hwnd, hAccelTable, msg))        {            TranslateMessage(msg);            if(msg.message ==WM_COMMAND) WinExec("cmd /k echo TranslateMessage()ok",SW_SHOW);      //加上这句            DispatchMessage(msg);            if(msg.message ==WM_COMMAND) WinExec("cmd /k echo DispatchMessage()ok",SW_SHOW);       //加上这句        }     }   在WndProc()中: case IDM_ABOUT:        //DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);  //这句屏蔽掉        MessageBox(NULL,"in about","",MB_OK);  //加上这句,这样父窗就可以点出来了     发现,点菜单的ABOUT..., WinExec(显示TranslateMessage()ok)执行,显示出MessageBox;MessageBox关闭后,WinExec(显示DispatchMessage()ok)才会执行。    OK,符合正常的消息处理原则,即DispatchMessage()要等到WndProc()执行完才会返回。   重新开始试: 1. 点菜单的ABOUT..., WinExec(显示TranslateMessage()ok)执行,显示出第一个MessageBox。 2. 再到主窗,点菜单的ABOUT..., 显示出第二个MessageBox,但WinExec(显示TranslateMessage()ok)没有执行!! 3. 关闭第一个MessageBox,WinExec(显示DispatchMessage()ok)仍没有执行。   4. 最后,关闭第二个MessageBox,DispatchMessage()ok)才执行。   结论: 对话框、消息框等子窗口是用自已默认的消息循环,而不是重入到父窗的消息循环!! 主窗阻塞了,第1个子窗负责消息循环,调用线程的消息响应函数(包括主窗、第1个子窗的消息响应函数); 第1个子窗阻塞了,第2个子窗负责消息循环,调用线程的消息响应函数(包括主窗、第1个子窗、第2个字窗的消息响应函数);。。。 子窗是一级一级阻塞下去的,后一个子窗关闭了,才能使前一个子窗的消息响应函数解除阻塞。 如果处在中间的子窗关闭了,它的消息响应函数仍还在阻塞中!只有它后面的子窗都关闭了,它的消息响应函数才会返回。       所以,如果是基于消息来处理事件,比如,网络SOCKET异步编程,消息处理函数中,有 用到消息框MessageBox或对话框,则要小心 ,以免多个事件消息同时发生。因为消息框出现后,当前消息处理函数阻塞了,但消息循环仍在进行,如果有新的消息事件产生,则会运行新的消息处理函数,则有可能会产生不希望的后果。     四、后来,试验网络SOCKET异步编程,确实,弹出MessageBox后,消息循环仍在继续,如果有收到FD_READ、FD_ACCEPT等,都会执行消息处理函数。 如果消息处理函数中弹出MessageBox,这时下一个消息来了,则会再运行一个新的消息处理函数!而不是阻塞。即 消息处理函数同时被多次调用,多个并存!         =================================== 下面引用网络的文章: ===================================   http://hi.baidu.com/suninf/blog/item/c3b7c738fa751cf4b311c74d.html DispatchMessage 2008年10月18日 星期六 14:33 windows消息处理机制是这样的: 首先系统(也就是windows)把来自硬件(鼠标,键盘等消息)和来自应用程序的消息 放到一个系统消息队列中去。 而应用程序需要有自己的消息队列,也就是线程消息队列, 每一个线程有自己的消息队列 ,对于多线程的应用程序就有和线程数目相等的线程消息队列。 winsows消息队列把得到的消息发送到线程消息队列,线程消息队列每次取出一条消息发送到指定窗口,不断循环直到程序退出。这个循环就是靠消息环(while(GetMessage()) TranslateMessage();DispatchMessage(); 实现的。 GetMessage()只是从线程消息中取出一条消息,而DispatchMessage 则把取出的消息发送到目的窗口。如果收到WM_CLOSE消息则结束循环,发送postqiutmessage(0),处理WM_DESTROY销毁窗口!    其实问题的关键在于:DispatchMessage到底干了什么? 如果只是去调用相应的窗口,那自己写个switch不就可以了 ? DispatchMessage与switch不同之处在于DispatchMessage会 先调用windows,进入管态(大概是range 0),然后再由windows调用 窗口的函数。 为什么这么麻烦? 因为这样windows就可以知道你的程序运行到什么情况了, windows来调用你的窗口,这样你的窗口返回的时候,windows就知道你已经处理过一个消息了,如果没有新的消息进入消息队列,windows就不再会给你的进程分配时间片。 如果是你自己写switch的话,windows就不可能这样灵活的分配时间,资源利用率就会降低。   那么还要消息循环干什么,windows直接把消息发给窗口不就可以了吗? 因为你要在消息循环里把KEY_DOWN和KEY_UP组合成WM_CHAR,还可以直接屏蔽掉许多对你来说无用的消息,加快速度。       GetMessage:      从线程的消息队列取出一个消息 。GetMessage是从系统为每个应用程序自动分配的消息对列的头部得到一个消息。     TranslateMessage:     将msg结构传给Windows,进行一些转换,比如A键按下,转换成WM_CHAR消息等 。TranslateMessage是对一些键盘事件做预处理。TranslateMessage是翻译需要翻译的消息。  翻译消息不是简单的转换,一个消息被翻译后,可能会产生几个消息。   DispatchMessage():      再将msg结构传给Windows,Windows将该消息发给窗口过程,由窗口过程处理。  DispatchMessage()则会把翻译好的消息发送到系统的消息处理函数中,而这个函数又会把这个消息传递到注册窗体时用户指定的消息处理函数中 前面已经介绍从系统队列里获取一条消息,然后经过快捷键的函数检查,又通过字符消息函数的转换,最后要做的事情就是调用DispatchMessage函数,它的意思就是说要把这条消息发送到窗口里的消息处理函数WindowProc。     ===================================   消息的循环过程大致为(关于消息的具体情况不再说明)    1. 消息循环调用GetMessage()从消息队列中查找消息进行处理,如果消息队列为空,程序将停止执行并等待(程序阻塞)。    2. 事件发生时导致一个消息加入到消息队列(例如系统注册了一个鼠标点击事件),GetMessage()将返回一个正值,这表明有消息需要被处理,并且消息已经填充到传入的MSG参数中;当传入WM_QUIT消息时返回0;如果返回值为负表明发生了错误。     3. 取出消息(在Msg变量中)并将其传递给TranslateMessage()函数,这个函数做一些额外的处理:将虚拟键值信息转换为字符信息。这一步实际上是可选的,但有些地方需要用到这一步。     4. 上面的步骤执行完后,将消息传递给DispatchMessage()函数。DispatchMessage()函数将消息分发到消息的目标窗口,并且查找目标窗口过程函数,给窗口过程函数传递窗口句柄、消息、wParam、lParam等参数然后调用该函数。    5. 在窗口过程函数中,检查消息和其他参数,你可以用它来实现你想要的操作。如果不想处理某些特殊的消息,你应该总是调用DefWindowProc()函数,系统将按按默认的方式处理这些消息(通常认为是不做任何操作)。    6. 一旦一个消息处理完成,窗口过程函数返回,DispatchMessage()函数返回,继续循环处理下一个消息。     ================================   DispatchMessage将消息分发到窗口函数中,请问:DispatchMessage是直接返回还是等待WndProc处理完毕再返回?   用::DiapatchMessage派送消息,在窗口处理过程(WinProc,窗口函数)返回之前,他是阻塞的,不会立即返回,也就是消息循环此时不能再从消息队列中读取消息,直到::DispatchMessage返回。如果你在窗口函数中执行一个死循环操作,就算你用   PostQuitMessage函数退出,程序也会down掉。 while(1) {         PostQuitMessage(0);   //程序照样down. }     所以,当窗口函数处理没有返回的时候,消息循环是不会从消息队列中读取消息的。这也是为什么在 模式对话框 中要自己用无限循环来继续消息循环,因为这个无限循环阻塞了原来的消息循环,所以,在这个无限循环中要用GetMessage,PeekMessage,DispatchMessage来从消息队列中读取消息并派送消息了。要不然程序就不会响应了,这不是我们所希望的。   模式对话框是卡住了啊,只不过它内部死循环中又有PeekMessage,GetMessage什么的了,所以不会对界面操作产生影响   我记得IsDialogMessage只适用于模式对话框吧,非模式对话框不需要的。 还有,如果是模式对话框,下面的窗口还是可以处理WM_PAINT的,你移动上面的模式对话框,下面的窗口可以自己重画   刚才试了一下,DispatchMessage果然是会卡住等待WndProc返回才返回的。模式对话框的确是有内嵌消息循环的,包括MessagaBox也是一样。         WM_PAINT和WM_TIMER都是优先级不同的,WM_TIMER优先级最低,只有队列里没有其他消息才会执行,WM_PAINT则较高   从窗口创建开始说: CreateWindowEx,这个会向窗口例程直接投递WM_CREATE,而不进入消息队列。其他消息则是比较正常的经过消息队列,然后通过GetMessage和DispatchMessage取消息和分发到相应例程,直到取到WM_QUITE就结束消息循环。 对于按键和鼠标消息则是先进入系统消息队列,然后系统队列会分发到相应的线程消息队列。   记住,消息队列是线程所有,并非窗口所有和进程所有,当然,系统队列例外。       ===================================================================   刚才学了用 c 和 windows API 创建一个简单的windows 窗口程序,步骤如下:   1.设计一个窗口类 2.创建窗口 3.显示窗口 4.定义消息结构体,开始消息循环,如:    while(GetMessage(msg,NULL,0,0)){        略...            } 5.编写窗口过程函数,如:   LRESULT CALLBACK WinSunProc(参数略){       switch(uMsg)       {          case 某一事件;               执行某函数;               break;          case 某一事件;               执行某函数;               break;          default;                略                 }   }   我的问题是, 当发生了一个消息时, 会执行switch 语句 中的某条case语句, 就是在此时此刻,while语句还在监听消息吗??????         如何你在窗口函数case不返回的话这个窗口就会没响应的,你可以试试看在一个case里写Sleep(5000)   有些人已经说对了,GetMessage只负责从消息队列里面取出一条消息,TranslateMessage将键盘敲键的消息转换成WM_CHAR消息,DispatchMessage就负责调用你的窗口函数,其实相当于 ... DispatchMessage(...) {     ....      WinSunProc(...):  //事实上这里是通过你注册窗口类时候给Windows的函数指针来实现的,但是效果和直接调用一样。 } 现在整个流程就很清楚了,GetMessage - DispatchMessage - WinSunProc 然后再返回到主循环进行下一条消息的操作,如果你在WinSunProc里面一直不返回,那么程序是无法处理下条消息的。 处理消息的时候如果又有其他消息过来是没关系的,Windows的GetMessage是从消息“队列”里面去消息的,没来得处理的消息是会排队在消息队列里面的,微软说了Windows的消息队列足够长,一般不会出现消息丢失的情况,具体没说多长,可能根据操作系统版本不同有不同的长度限制。 另外GetMessage还有个特性,如果程序的消息队列是空的,也就是没有消息了,那么GetMessage就不会返回,直到等到下一条消息来再返回,Windows会将处于等待的程序转入Idle模式,所以那个while循环是不会出现CPU100%的占用率的。 如果你希望在程序没有消息的时候在后台做点什么事情,那么就可以利用 PeekMessage ,典型的 MFC就是利用了PeekMessage来运作消息循环的 ,PeekMessage在队列中有消息的时候则把消息取回, 没消息的时候也会立刻返回 ,这样你就可以在没消息的时候做点别的事情。 MFC的CWinApp类在Run这个函数中包含了消息循环,在没有消息的时候,Run会去调用 CWinApp::OnIdle ,默认的OnIdle会负责释放不需要再使用的动态连接库文件。 如果Run里面的PeekMessage取到消息,他则调用 CWinApp::PumpMessage 函数,PumpMessage就负责调用DispatchMessage把消息转交给窗口函数。       windows在处理消息时,会使用一个队列来存放所有消息,即消息队列。在执行case语句时,虽然窗口没有关心消息队列,但是如果此时又来了一个消息,windows会自动将该消息放入队列之中,保证消息不会丢失。当case语句处理完毕,窗口再一次运行到GetMessage时,会查看队列中有没有未处理的消息存在,通过这种方式获取之前发生但还没有处理的消息,因此不会出现对消息视而不见的情况       windows采用消息队列来处理消息,没侦听到一个事件,系统会将此消息加到消息队列,再按顺序或者按权重来处理消息。        所有创建了窗口的Windows程序,都需要运行一个消息循环 :        while (GetMessage(msg, hWnd, 0, 0) 0)          {                   TranslateMessage(msg);                   DispatchMessage(msg);          }          这里的hWnd就是创建的窗口句柄,上述循环会不断的把该窗口(hWnd)相关的消息取出来,并分发到消息处理函数当中。          GetMessage函数不是用来监听的,是用来获取当前线程消息队列当中的消息的,其中的第二个参数如果传递一个窗口句柄,那么就会获取该窗口相关的消息,如果传NULL,那么会将线程消息队列中所有的消息都取出来。如果创建了多个窗口,而只对其中一个窗口句柄调用GetMessage形成消息循环,那么别的窗口都会毫无响应。          补充说明: 消息队列是操作系统为每个需要处理消息的线程创建的,任何线程只要调用过与消息有关的函数(如GetMessage,PeekMessage),操作系统就会为该线程创建消息队列 。       GetMessage在消息列队中没有消息时是阻塞的,也就是没有消息的情况下他会通知系统把时间片交给其他进程或线程     ==================================== 1 :消息处理中第一条消息是不是 WM_CREATE 2:当接收到WM_CREATE消息时,他的附加参数中有没有 窗口的实例句柄 在那个参数中或者 有没有其他办法在消息处理中获得窗口的实例句柄 hInstance 3;如果将WM_CREATE交给系统处理的话。。系统做了什么   重复的说下过程吧,首先是定义一个窗口类,然后注册窗口类,然后依照你前边定义好的窗口类来创建一个窗口。以上就是CreateWindow函数调用结束前所做的事情,然后会调用ShowWindow将这个创建好的窗口显示出来。 接下来遇到消息循环了,程序开始从消息队列中取消息。 首先遇到的消息就是WM_CREATE(正如你所问到的),这条消息是由系统向你的应用程序投递的。然后系统会调用你写的那个“回调函数”,它依照你写的WM_CREATE内容来创建一些控件或子窗体。(注意在这个消息中并不创建主窗口,因为创建主窗口的工作早在ShowWindow前就创建好了) 在创建都完成以后就会把整个窗口的样子绘制出来,然后程序就可以处理别的消息啦。 至于第二个问题,它是得到不应用程序的实例句柄的。它的两个赋加参数中,wParam不会被使用,而lParam则是一个指向 CREATESTRUCT 结构体的指针,用于创建子窗体(控件)的一些必要信息。 你要想得到实例句柄要调用函数,最典型的就是GetWindowLong函数。利用该函数取应用程序实例句柄的调和方式如下: HINSTANCE hAppInstance = (HINSTACE)GetWindowLong(hwnd,GWL_HINSTANCE); 其参数有两个,第一个参数是主窗口的句柄,第二个参数是一个标记,代表你要取实例句柄,该函数还有别的功能,楼主可以自行查阅MSDN 还有其它的函数可以得到实例句柄,比如GetModuleHandle(NULL)的返回值也是实例句柄。 第三个问题已经在前边讲过了,注意你问的不对,这个消息本来就是由系统处理的,并不是你的程序处理的。    
相关资源
  • 所需E币: 1
    时间: 2023-11-10 11:45
    大小: 25.85KB
    上传者: Argent
    第14讲Linux阻塞和非阻塞IO实验_笔记
  • 所需E币: 0
    时间: 2022-7-9 09:44
    大小: 1.56MB
    上传者: ZHUANG
    基于大数据的通信网络阻塞故障检测系统设计
  • 所需E币: 1
    时间: 2022-7-7 16:04
    大小: 1.56MB
    上传者: ZHUANG
    基于大数据的通信网络阻塞故障检测系统设计
  • 所需E币: 0
    时间: 2022-5-3 16:18
    大小: 130.1KB
    上传者: ZHUANG
    多优先级业务分组交换网的阻塞性能分析算法
  • 所需E币: 1
    时间: 2022-1-8 10:45
    大小: 925.56KB
    上传者: 西风瘦马
    raw-os实例之——多对像阻塞(阻塞在同种内核对像)
  • 所需E币: 1
    时间: 2022-1-8 10:45
    大小: 934.95KB
    上传者: 西风瘦马
    raw-os实例之——多对像阻塞(阻塞在多种内核对像)
  • 所需E币: 1
    时间: 2021-4-13 17:21
    大小: 3.75MB
    上传者: ZHUANG
    基于DSP的脉冲阻塞式交-交变频控制系统研究
  • 所需E币: 5
    时间: 2019-12-25 09:40
    大小: 167KB
    上传者: quw431979_163.com
    Verilog阻塞和非阻塞分析Verilog非阻塞赋值的仿真/综合问题源文件作者:CliffordE.Cummings(SunburstDesign,Inc.)原标题:NonblockingAssignmentsinVerilogSynthesis,CodingStylesThatKill!ATTN:所有括号内“外注”为理解方便或有疑问的地方,原文里并没有。所有翻译都是为遵循“共同进步”的理想但并没有去努力得到原作者的任何书面和其它方式许可,所以仅供大家参考。本人英文和设计水平都极有限,所以不能保证与原文的精确一致和正确(只能以“驽马十步”稍作安慰吧),惭愧之后还希望大家多指教!在Verilog语言最难弄明白的结构中“非阻塞赋值”要算一个。甚至是一些很有经验的工程师也不完全明白“非阻塞赋值”在仿真器(符合IEEE标准的)里是怎样被设定执行的,以及什么时候该用“非阻塞赋值”。这篇文章将介绍怎样设定“非阻塞赋值”和“阻塞赋值”,给出了重要的使得编码可以被正确地综合的编码指导方针,和避免仿真竞争的编码风格细节。1.0介绍众所周知的逻辑建模方针是:*在always块里用“阻塞赋值”产生组合逻辑。*在always块里用“非阻塞赋值”产生时序逻辑。但是为什么?(外注:在实现组合逻辑的assign结构中,当然采用阻塞赋值语句否则的话编译工具会提醒你进行修改的。)普通的回答是:那只……
  • 所需E币: 5
    时间: 2020-1-4 23:20
    大小: 93.95KB
    上传者: 2iot
    深入理解阻塞和非阻塞赋值……
  • 所需E币: 4
    时间: 2020-1-14 09:58
    大小: 52.29KB
    上传者: 二不过三
    噪声阻塞式手机干扰机设计选题号16噪声阻塞式手机干扰机设计张晓发1袁乃昌1万志坤21国防科技大学四院微波中心湖南长沙4100732江南遥感应用研究所上海200436摘要本文设计了一种结构简单的可用于小型保密会议的噪声阻塞式手机干扰机介绍了方案设计原理实现了样机并给出了测试结果实验结果表明对50m2的室内干扰效果良好关键词噪声阻塞手机干扰机1引言移动通讯技术的迅速发展和广泛应用给人们的生活带来了极大的便利同时也使失密泄密的渠道更加难以控制通过手机的失密泄密行为无论是在军事上还是在商业竞争上都显得日益重要同时也向保密技术和电子对抗技术提出了极大的挑战本文是对手机干扰装置研究的一种尝试设计并实现了一种利用VCO进行噪声调频的射频噪声干扰装置具有两路射频输出分别对目前GSM和CDMA网络常用的两个频段进行阻塞式干扰在小范围空间内由于干扰机相对于手机联络的基站具有距离优势在手机工作的频带内噪声功率远大于手机信号功率从而可以有效的干扰手机的正常通讯本文的第二部分较详细的介绍了该干扰机的原理结构及硬件实现第三部分给出了频谱测试及室内干扰实验的结果2噪声调频手机干扰机设计2.1干扰机原理干扰机原理框图如下直流控制1基带噪声放VCO2射频噪声放大直流控制2射频噪声放大基带噪声VCO1图1干扰机原理框图干扰机的工作原理如下噪声源产生的基带噪声经放大电路放大后分成两路分别和调节中心频率的直流电压一起加在两个VCO的控制端直流电压控制射频噪声的频谱中心位置基带噪声对VCO输出频率调制形成调频噪声[1]其幅度决定了射频噪声的频谱宽度两路射频噪声分别覆盖手机工作的两个频段经一级功率放大通过两个全向天线分别辐射出去……
  • 所需E币: 3
    时间: 2020-1-14 19:14
    大小: 60.04KB
    上传者: 2iot
    学好verilog的关键一步---阻塞和非阻塞赋值,阻塞和非阻塞赋值……
  • 所需E币: 5
    时间: 2020-1-14 19:19
    大小: 94.69KB
    上传者: 微风DS
    深入理解阻塞和非阻塞(很好),深入理解阻塞和非阻塞……
  • 所需E币: 3
    时间: 2020-1-14 19:20
    大小: 60.04KB
    上传者: quw431979_163.com
    学好verilog的关键一步---阻塞和非阻塞赋值3,学好verilog的关键一步---阻塞和非阻塞赋值3……
  • 所需E币: 5
    时间: 2020-1-14 19:20
    大小: 145.14KB
    上传者: givh79_163.com
    Verilog编码与综合中的非阻塞性赋值(中文)[FOR...,Verilog编码与综合中的非阻塞性赋值(中文)……