WaitForMultipleObjects返回WAIT_FAILED的问题

duanhongmai   2008-7-9 15:39 楼主
情况如下:
设置了一个全局变量HANDLE g_hevInt[3];
在程序里创建了三个事件:
g_hevInt[0] = CreateEvent(NULL,FALSE,FALSE,NULL);
g_hevInt[1] = CreateEvent(NULL,FALSE,FALSE,NULL);
g_hevInt[2] = CreateEvent(NULL,FALSE,FALSE,NULL);
这三个事件和中断相关,有中断发生则事件有效。
然后在IST这个线程里等待事件的发生。
第一次中断产生调用WaitForMultipleObjects函数得到的事件和相应的响应都是正确的。   
但是接下来WaitForMultipleObjects一直返回WAIT_FAILED,不知是什么原因?
GetLastError()返回值是6,即INVALID HANDLE
但是我输出三个句柄的值以及g_hevInt的值,发现第一次调用时和返回WAIT_FAILED时的值都是一致的,那为什么会产生这个错误呢?
还请大家帮忙分析一下。^_^,先行谢过。
线程回调函数代码如下:
DWORD IST(LPVOID pArg)
{
        DWORD ret;
        while (1)
        {
              ret = WaitForMultipleObjects(3,g_hevInt,FALSE,INFINITE);
              if(ret == WAIT_FAILED)
              {
                RETAILMSG(1,(TEXT("WAIT_FAILED here.\r\n")));
                RETAILMSG(1, (L"LastError = %d \r\n", GetLastError()));
              }
              else if (ret != WAIT_TIMEOUT)
              {
                    RETAILMSG(1, (L"Event [%d]  is triggered.\r\n", ret));
                    ResetEvent(g_hevInt[ret]);
                    InterruptDone(g_EINTSysIntr[ret]);
              }
              else
              {
                    RETAILMSG(1,(TEXT("EINT_IntrThread Exit.\r\n")));
                    return 0;
              }
        }
        return 1;
}

回复评论 (18)

WaitForMultipleObjects函数不能用于使用过“InterruptInitialize”函数的事件。
点赞  2008-7-10 00:20
InterruptInitialize
只能用在WaitForSingleObject

而且
先InterruptInitialize
才能
WaitForSingleObject
点赞  2008-7-10 09:57
先谢谢楼上两位。
有两个疑问:
1.我想在一个线程里同时等待几个中断事件的发生,这种方法不能用的话采取什么样的方式比较好?

2.help上关于InterruptInitialize的说明里说。
A WaitForMultipleObjects call with hEvent will fail。
第一次调用WaitForMultipleObjects是正确的,而之后出错时我打印事件句柄的值并没有任何变化,
也就是好像句柄值并未失效,这样的话为什么会出错呢?


点赞  2008-7-10 13:42
ResetEvent(g_hevInt[ret]); //咦,这样envet就不可用了,干吗这样玩?
点赞  2008-7-10 15:03
引用: 引用 4 楼 shuiyan 的回复:
ResetEvent(g_hevInt[ret]); //咦,这样envet就不可用了,干吗这样玩?

这个是我测试了以为这个事件需要手动清除信号状态,后来没用,:-)
点赞  2008-7-10 15:33
你用一个event,WaitForSingleObject能成功吗?
WaitForMultipleObjects时,加判断,看看第一次到底是哪个event触发的。

改好后,看看驱动打印的消息。
点赞  2008-7-10 16:03
to shuiyan:
用一个event,WaitForSingleObject是OK的,没问题。
WaitForMultipleObjects时,第一次event也确实是发生了的那个中断没问题。
而且出错时事件句柄的值,包括g_hevInt这个地址的值都没有发生任何变化。
我试过
if(!g_hevInt[0])
{
  RETAILMSG;
}

if(g_hevInt[0]==INVALID_HANDLE_VALUE)
{
  RETAILMSG;
}
这两种方式判断句柄是否有效,但是都没有问题啊。。。

太奇怪了。
WaitForMultipleObjects结束后只是把那个事件置位无信号状态,但是为什么会对于InterruptInitialize 的时间不能用呢,太奇怪了。而且根据测试结果好像句柄的值也没有变化啊。。。
点赞  2008-7-10 16:14
msdn里没有的,不一定不能用。
msdn明确说不能用的,估计就是不能用。这个就是理由了。
点赞  2008-7-10 17:52
好吧 。呵呵。
我想在一个线程里等待多个中断事件的话应该怎么做?我只想到下面一种方式,但是这种方式中断优先级轮转,实时性太差了,有没有别的方式可以实现这种要求的?
DWORD IST(LPVOID pArg)  
{  
    DWORD ret;  
    while (1)  
    {  
              if(WAIT_OBJECT_0==WaitForSingleObject(g_hevInt[0],100))
              {
                    RETAILMSG(1, (L"Event 0 is triggered.\r\n"));
              }
              if(WAIT_OBJECT_0==WaitForSingleObject(g_hevInt[1],100))
              {
                    RETAILMSG(1, (L"Event 1 is triggered.\r\n"));
              }
              if(WAIT_OBJECT_0==WaitForSingleObject(g_hevInt[2],100))
              {
                    RETAILMSG(1, (L"Event 2 is triggered.\r\n"));
              }
    }  
    return 1;  
}  
点赞  2008-7-10 21:33
只要不是用InterruptInitialize 初始化的都可以用

WaitForMultipleObjects
点赞  2008-7-11 09:45
to lenux:
在这种情况下事件是使用InterruptInitialize和中断相关联的,如果不用这种方式的话,
在CE下还有什么方式可以判断中断是否发生然后进行处理呢?

ps:是否可以再BSPIntrActiveIrq函数中直接处理一下?不过这样做的话就违背了中断分为ISR和IST的方法了。。。貌似不太妥哇。。。
点赞  2008-7-11 10:02
啊?还没取消用InterruptInitialize 对这几个event设置啊?

只要SetEvent之后,这些event就可以在WaitMultipleObjects里面使用了。

在别的地方(比如希望与该Event挂钩的中断线程)对其SetEvent()就行。

点赞  2008-7-11 10:10
to shuiyan:
在别的地方(比如希望与该Event挂钩的中断线程)对其SetEvent()就行?
现在的情况是使用这个event是否有信号来判断中断是否发生。InterruptInitialize这个函数调用时会自动调用OALIntrEnableIrqs的,所以这种方式很难更改吧?
你的意思是每个中断起一个线程然后在该中断线程里SetEvent()?用两套event?

可能我有点没明白你的意思。可以描述下你的实现方式么?
或者是有不用InterruptInitialize而实现整个中断流程的方法?
有别的判断中断是否发生然后进行处理的方法?
ps:我是想在一个中断线程里对多个事件进行响应,就不用起一堆线程了。
点赞  2008-7-11 11:17
to shuiyan:
在别的地方(比如希望与该Event挂钩的中断线程)对其SetEvent()就行?
现在的情况是使用这个event是否有信号来判断中断是否发生。InterruptInitialize这个函数调用时会自动调用OALIntrEnableIrqs的,所以这种方式很难更改吧?
你的意思是每个中断起一个线程然后在该中断线程里SetEvent()?用两套event?

可能我有点没明白你的意思。可以描述下你的实现方式么?
或者是有不用InterruptInitialize而实现整个中断流程的方法?
有别的判断中断是否发生然后进行处理的方法?
ps:我是想在一个中断线程里对多个事件进行响应,就不用起一堆线程了。
点赞  2008-7-11 11:19
奇怪..用Waitforsingleobject()不行吗,为什么一定要用WaitMultipleObjects,
我试过WaitForSingleObject等待多个的,可以...处理完一个就close.
点赞  2008-7-11 16:23
to xyj0663:
你处理的流程是啥样的?这样?
DWORD IST(LPVOID pArg)  
{  
    DWORD ret;  
    while (1)  
    {  
              if(WAIT_OBJECT_0==WaitForSingleObject(g_hevInt[0],100))
              {
                    RETAILMSG(1, (L"Event 0 is triggered.\r\n"));
              }
              if(WAIT_OBJECT_0==WaitForSingleObject(g_hevInt[1],100))
              {
                    RETAILMSG(1, (L"Event 1 is triggered.\r\n"));
              }
              if(WAIT_OBJECT_0==WaitForSingleObject(g_hevInt[2],100))
              {
                    RETAILMSG(1, (L"Event 2 is triggered.\r\n"));
              }
    }  
    return 1;  
}  
点赞  2008-7-11 16:39
好像真只有2套event了,一套SigleObject,在对应的ISR里面Set MultipleObjects里面的event。
点赞  2008-7-12 11:37
ResetEvent(g_hevInt[ret - WAIT_OBJECT_0]);
点赞  2009-12-2 08:54
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复