【问题标题】:Python COM events handling blockedPython COM 事件处理被阻止
【发布时间】:2014-08-21 16:37:30
【问题描述】:

我正致力于在 Python 中实现 COM,因为我必须在两个不同的软件(dSPACE HIL 环境和 Vector CANOE 环境)之间进行交互。我的想法是我在 (CANOE) CAPL 脚本中更改环境变量,并且我想在事件发生时对 dSPACE HIL 执行一些操作。现在我还没有实现任何线程。

(1) 所以第一个问题是当我尝试使用简单的睡眠来确保在 CANOE 中完成测试执行时,由于 python 睡眠阻止了 CANoe 执行并且我得到了 pythoncom错误:每当环境变量更改时,Python 错误调用 COM 方法。因此,只有在 Python 中的睡眠结束后才开始执行 CANOE,并且我在 CANOE 中弹出以下消息,说服务器忙。

当我使用消息框时,即用户必须在测试完成后按下按钮,执行工作正常。我想用其他一些机制来代替它,比如睡眠。请让我知道如何解决此问题。我在下面粘贴了我的脚本。

class EnvironmentEvents:
    def __init__ ( self ) :
        print "Initializing Environment Event Class"
 
    def OnChange ( self , value ) :
        StopTestExecution = Value
        print '% 3.2f' % StopTestExecution
        print ( 'Environment Variable Value Changed' )
 
# # # # # # # # # # # # # # # # # # # INITIALIZE CONTROL DESK # # # # # # # # # # # 
MyControlDeskHandler = Controldesk_Handler. CONTROLDESK_HANDLER ()
 
# # # # # # # # # # # # # # # # # # # INITIALIZE CANOE # # # # # # # # # # # # # #  
MyCAN                = Dispatch ( 'CANoe.Application' )
MyCANMeasurement     = MyCAN. Measurement
MyCANEnvironment     = MyCAN. Environment . GetVariable ( "env_COM_BatteryVoltage" )
My events            = Dispatch WithEvents ( MyCANEnvironment , EnvironmentEvents )
 
Test Setup = MyCAN. Configuration . Test Setup
    TestEnvs = test setup. Test Environments
Testenv = TestEnvs. Item ( 1 )
Testenv. ExecuteAll ( )            
 
    ## Msgbox (0, "Test Completed", "info", 16) ## with a message box everything is working fine

    while ( StopTestExecution > 0 ):
            print '% 3.2f' % StopTestExecution
            Sleep ( 500 )    

我的想法是将事件变量值从 CAPL 发送为 0 以停止执行。直到那个时候循环必须继续。但这不起作用。

(2) 然后第二个问题是当 OnChange 事件发生时,我想更改 dSPACE HIL Control Desk 中的某些内容。为此,我必须使用 dSPACE 提供的库。但问题是我如何在 Events 类中访问这个库及其方法。我尝试将 dSPACE 库对象和参数作为类 EnvironmentEvents 的参数传递,如下所示。但是python给了我以下错误。现在我只是将它用作全局并且它工作正常。但如果有更好的选择,我想避免它。

class EnvironmentEvents:
    def __init__ ( self , ControlDeskhandler , Path ) :
        print "Initializing Environment Event Class"
        self . MyHandler = ControlDeskhandler
        self . MyPath = Path
 
    def OnChange ( self , value ) :
        StopTestExecution = Value
        print '% 3.2f' % StopTestExecution
        self . MyHandler . Write_Variable ( self . MyPath , Value )
        print ( 'Environment Variable Value Changed' )

    My events             = Dispatch WithEvents(MyCANEnvironment , Environment Events ( MyControlDeskHandler ,'Model Root/VOLTAGEOUT/ Value'))
 
Traceback ( most recent call load ) :
    .     File "C: \ P rogram Files (x86) \ C ommon Files \ d SPACE \ P ython25 \ l ib \ s ite-packages \ w in32com \ c lient \ __init__.py     " , line 304 , in Dispatch WithEvents
 result_class = new . classObj ( "COMEventClass" , ( disp_class , events_class , user_event_class ) , { "__setattr__": _event_setattr_ } )
TypeError : instance ( ) takes at most 2 arguments ( 3 givenName )
[ dbg ] >>>

请帮助我解决这些问题。如果您需要任何其他信息,请告诉我。

【问题讨论】:

  • Sleep 的问题是它在睡眠时不发送消息,COM 需要处理消息才能工作。 (MessageBox 确实会发送消息,所以它可以工作。)不幸的是,我对 Python 不够熟悉,无法告诉您如何在发送消息时睡觉。
  • 问题已解决。正如 Eric 所指出的,睡眠不允许我在睡眠发挥作用之前使用 pythoncom.PumpWaitingMessages() 泵送消息和使用。谢谢。

标签: python events com handler


【解决方案1】:

Sleep 的问题在于它不会在睡眠时发送消息,并且 COM 需要处理消息才能工作。 (MessageBox 确实会发送消息,所以它可以工作。)

这里的典型解决方案是使用MsgWaitForMultipleObjectsEx 和消息泵。显然 pythoncomwin32event 有适当的包装器。

win32Event.MsgWaitForMultipleObjectsEx 需要一个句柄等待;如果您需要等待特定时间,那么最好创建一个可等待计时器。奇怪的是,根据文档,win32eventOpenWaitableTimer,但没有CreateWaitableTimer。希望这是一个文档错误。

无论如何,如果您不需要特定时间,您可以使用win32event.CreateEvent 创建一个win32 事件。它可以是匿名事件;你所需要的只是等待。在您的 OnChange 处理程序中,您可以设置事件。

一旦你有一个事件,你可以等待。原谅我可怕的蟒蛇;这是从C音译过来的。

def WaitAndPumpMessagesWithTimeout(hWaitHandle, dwMilliseconds) :
{
    fContinue = TRUE;

    while (fContinue)
        dwWaitId = win32event.MsgWaitForMultipleObjectsEx(1, hWaitHandle, dwMilliseconds, win32event.QS_ALLINPUT, win32event.MWMO_INPUTAVAILABLE);
        if (dwWaitId == win32event.WAIT_OBJECT_0)
             return TRUE;
        elif (dwWaitId ==  WAIT_OBJECT_0 + 1)
            pythoncom.PumpWaitingMessages();
        elif (dwWaitId  == WAIT_TIMEOUT)
           return FALSE;
    return TRUE;
}

【讨论】:

    猜你喜欢
    • 2012-11-18
    • 1970-01-01
    • 2015-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-06
    • 1970-01-01
    • 2017-02-07
    相关资源
    最近更新 更多