WinCE下应用程序的单实例运行

时间:2022-05-17 17:28:08

      实现应用程序的单实例运行有很多种方式。如果是有窗口的应用程序,可以通过FindWindow()查找窗口来确认是否已有同名窗口存在。如果是无窗口的应用程序,可以用互斥体等内核对象实现。一般来说,在程序的入口处检查是否已有实例在运行。如果没有,则继续执行。如果有,则退出本次运行。基本流程如下图所示。

      WinCE下应用程序的单实例运行

      以互斥体实现的单实例参考代码如下。

int  _tmain( int  argc, _TCHAR *  argv[])
{
    HANDLE hMutex 
=  CreateMutex(NULL, FALSE, TEXT( " SINGLE_INSTANCE " ));
    
    
if ( ! hMutex)
    {
        RETAILMSG(
1 ,(TEXT( " \r\nFailed to CreateMutex()... " )));
        
return   0 ;
    }
    
    
if  ( GetLastError()  ==  ERROR_ALREADY_EXISTS)
    {
        RETAILMSG(
1 ,(TEXT( " \r\nApp already run,CloseHandle(%x)... " ), hMutex));
        CloseHandle(hMutex);
        
return   0 ;
    }    

    RETAILMSG(
1 ,(TEXT( " \r\nApp is running (%x)... " ), hMutex));
    Sleep(
3000 );
    
    RETAILMSG(
1 ,(TEXT( " \r\nApp prepare to exit... " )));
    Sleep(
2000 );    

    RETAILMSG(
1 ,(TEXT( " \r\nApp exit(%x)... " ), hMutex));
    
return   0 ;
}

       项目中的倒车可视和DVD播放都使用了TCC89的CIF接口,它们不能同时运行。其中,DVD播放是应用程序实现的,而倒车可视在驱动中处理。在播放DVD的过程中,如果进入倒车可视,需首先关闭DVD播放程序,在退出倒车可视时,再启动DVD播放。DVD播放程序的退出时间较长,也就是T3,大概在2S左右。由于DVD播放程序是单实例运行的,所以在T3这个时间内启动第二个实例会失败,第一个实例也将退出。这样就会出现退出倒车可视后,DVD播放无画面的现象。

      为了解决这个问题,需要在检查单实例时做一些调整。如果检查到有实例在运行,并不马上退出,而是等一段时间后再检查一次,如果先前的实例退出了,则继续运行本次的程序。如果先前的实例仍然在运行,则退出本次运行。其中等待的时间,可以设置为T3的2倍。修改后的代码如下。

int  _tmain( int  argc, _TCHAR *  argv[])
{
    HANDLE hMutex 
=  CreateMutex(NULL, FALSE, TEXT( " SINGLE_INSTANCE " ));

    
if ( ! hMutex)
    {
        RETAILMSG(
1 ,(TEXT( " \r\nFailed to CreateMutex()... " )));
        
return   0 ;
    }

    
if  ( GetLastError()  ==  ERROR_ALREADY_EXISTS)
    {
        RETAILMSG(
1 ,(TEXT( " \r\nApp already run,CloseHandle(%x)111... " ), hMutex));
        CloseHandle(hMutex);

        Sleep(
4000 );

        hMutex 
=  CreateMutex(NULL, FALSE, TEXT( " SINGLE_INSTANCE " ));        
        
if ( ! hMutex)
        {
            RETAILMSG(
1 ,(TEXT( " \r\nFailed to CreateMutex()... " )));
            
return   0 ;
        }
        
        
if  ( GetLastError()  ==  ERROR_ALREADY_EXISTS)
        {
            RETAILMSG(
1 ,(TEXT( " \r\nApp already run,CloseHandle(%x)222... " ), hMutex));
            CloseHandle(hMutex);
            
return   0 ;
        }        
    }    

    RETAILMSG(
1 ,(TEXT( " \r\nApp is running (%x)... " ), hMutex));
    Sleep(
3000 );

    RETAILMSG(
1 ,(TEXT( " \r\nApp prepare to exit... " )));
    Sleep(
2000 );    

    RETAILMSG(
1 ,(TEXT( " \r\nApp exit(%x)... " ), hMutex));
    
return   0 ;
}

       修改前,运行的结果如下图所示。可以看到,在T2和T3时间内启动的实例都失败了。

      WinCE下应用程序的单实例运行

      修改后,运行的结果如下图所示。可以看到,在第一个实例结束后,第二个实例开始了运行,而其他的实例都逐一关闭。

      WinCE下应用程序的单实例运行

      对比两次执行的结果,可以看到,采用第二种方法应该能有所改善。但是否会带来新的问题呢?解BUG最怕的就是解了一个,却又引入一堆!