Share via


Asynchronous Application Requirements (Windows Embedded CE 6.0)

1/6/2010

If you choose to use asynchronous mode for the device-side component of your plug-in, there are several requirements that the device-side application must meet. In the asynchronous mode of communication, the application can run code at any time, and not only when the desktop-side component sends a query for data to the device.

Native Mode Requirements

The following list shows the requirements that your application must meet if you choose to use native mode for the application.

  1. Implement a WinMain entry point, and create a window with a message loop or another mechanism.
    The primary difference from a typical synchronous application is that the asynchronous application must stop the command handler when it exits.
    The following code sample displays a sample WinMain function from an asynchronous application.

    CDeviceRemoteTool g_DeviceRemoteTool;
    
    int WINAPI WinMain(
        HINSTANCE hInstance, 
        HINSTANCE hPrevInstance, 
        LPTSTR    lpCmdLine, 
        int nCmdShow)
    {
        MSG msg;
        // Perform application initialization:
        if (!InitInstance(hInstance, nCmdShow)) 
        {
            return FALSE;
        }
    
        // The lpCmdLine must be untouched
        g_DeviceRemoteTool.StartCommandHandler( 
            lpCmdLine, 
            g_DeviceRemoteTool.COMMANDHANDLER_ASYNC, 
        SysInfoCallback );
    
        while (GetMessage(&msg, NULL, 0, 0)) 
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    
        g_DeviceRemoteTool.StopCommandHandler ();
    
        return (int) 0;
    }
    
  2. Implement a callback function.
    There is one difference in the implementation of a callback function in asynchronous and synchronous applications. In an asynchronous application, the function must also include code that closes the application when the desktop-side component completes running your code.
    At this point, if the application has a window, it must call DestroyWindow, which calls the callback function with a command ID of COMMAND_EXIT.
    The following code sample displays a sample callback function that also includes a call to DestroyWindow.

    HRESULT STDAPICALLTYPE TestCallback(
        DWORD cmd, 
        const CCommandPacket* pCmdDataIn, 
        CCommandPacket* pCmdDataOut
    )
    {
    switch (cmd)
    {
        case END_COMMAND: // Defined in cecorecon.h
            DestroyWindow ( g_hWnd );
            break;
    }
        return S_OK;
    }
    
  3. Push data when needed.
    When your application is ready to push data to the desktop, it must create a command packet. The application calls the PushCommand method of the CDeviceRemoteTool object, and then frees the packet.
    The following code sample shows how to push a command to the desktop-side component in response to a WM_SETTINGCHANGE message from a window process.

    case WM_SETTINGCHANGE:
        CCommandPacket *pCmd = NULL;
        if (SUCCEEDED(g_DeviceRemoteTool.CreateCommand ( &pCmd )))
        {
            g_DeviceRemoteTool.PushCommand ( 
                COMMANDS_PushRefresh,    // A value the desktop
                                         // understands
                pCmd );
            g_DeviceRemoteTool.FreeCommand ( pCmd );
        }
        break;
    

Managed Mode Requirements

The following list shows the requirements that your application must meet if you have chosen to write an application that uses managed mode.

  1. Implement a Windows form whose constructor receives the command-line arguments.
    DeviceCommandTransport automatically stops the asynchronous transport in its finalizer, so you only need to create the transport in the constructor for the form.
    The following code sample shows a Windows form where a timer is created, whose event handler pushes command packets back to the desktop-side component.

    public Form1(string cmdline)
    {
        InitializeComponent();
        m_commandTransport = new DeviceCommandTransport(cmdline);
        //
        // Set up an event handler for packets sent from the
        // desktop to the device.
        m_commandTransport.CommandPacketReceived += 
        new CommandPacketEventHandler(
            m_commandTransport_CommandPacketReceived
        );
        //
        // Since this app runs until it dies, we want
        // to run the command handler asynchronously
        //
        m_commandTransport.StartCommandHandlerAsync();
    
        //
        // This timer is here for just one reason: To
        // demonstrate how to push commands up to the desktop
        //
        m_timer = new Timer();
        m_timer.Interval = 1000;
        m_timer.Tick += new EventHandler(m_timer_Tick);
        m_timer.Enabled = true;
    }
    
  2. Implement the event handler for command packets that come from the desktop-side component.
    The implementation of an event handler in an asynchronous application in managed code is the same as that of an event handler in a synchronous application.
    The following code sample shows how to close an application in response to a command if a Windows form is being used.

    void m_commandTransport_CommandPacketReceived(
        object sender, 
        CommandPacketEventArgs e
    )
    {
        //
        // Required for Aynchronous apps: This command ID is sent
        // when the desktop terminates the connection.
        //
        if (e.CommandPacketIn.CommandId ==
            CommandPacket.EndCommandID)
        {
            this.Close();
            Application.Exit();
        }
    
        if (e.CommandPacketIn.CommandId == 1)
        {
            CommandPacket packetOut = new CommandPacket();
            packetOut.AddParameterWORD(10);
            packetOut.AddParameterDWORD(100000);
            packetOut.AddParameterString("Hello Managed World!");
            packetOut.AddParameterBytes(new byte[]{11,22,33,44 });
            e.CommandPacketOut = packetOut;
        }
    }
    
  3. Push data to the desktop-side component when needed.
    When the application is ready to push data to the desktop-side component, it must create a command packet, and then call PushCommand on the DeviceCommandTransport object.
    The following code example displays sample code in which every time the timer from the constructor ticks, a simple command packet is sent back to the desktop.

    void m_timer_Tick(
        object sender, 
        EventArgs e
    )
    {
        CommandPacket packetOut = new CommandPacket();
        packetOut.CommandId = 1;
        m_commandTransport.PushCommand(packetOut);
    }
    

See Also

Concepts

Requirements for Device-Side Components