Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Not receiving messages after sometime

I am using JNA to access User32 functions (I dont think it has got to do with Java here, more of concept problem). In my application, I have a Java process which communicates with the Canon SDK. To dispatch any messages I am using the below function:

private void peekMessage(WinUser.MSG msg) throws InterruptedException {
    int hasMessage = lib.GetMessage(msg, null, 0, 0); 
    if (hasMessage != 0) {
        lib.TranslateMessage(msg);
        lib.DispatchMessage(msg);
    }
    Thread.sleep(1);
}

peekMessage is called in a loop and it all works well. Whenever an Image is taken from camera, I get the event and do the rest.

But I have observed, say after about 15 seconds (sometimes never or sometimes just at start) of no activity with camera, taking picture does not give me any download event. Later the whole application becomes unusable as it doesn't get any events from camera.

What can be the reason for this? Please let me know of any other info needed, I can paste the respective code along.

Edit:

Initialization:

Map<String, Integer> options = new HashMap<String, Integer>();
        lib = User32.INSTANCE;
        hMod = Kernel32.INSTANCE.GetModuleHandle("");
        options.put(Library.OPTION_CALLING_CONVENTION, StdCallLibrary.STDCALL_CONVENTION);
        this.EDSDK = (EdSdkLibrary) Native.loadLibrary("EDSDK/dll/EDSDK.dll", EdSdkLibrary.class, options);


 private void runNow() throws InterruptedException {

    while (!Thread.currentThread().isInterrupted()) {
        Task task = queue.poll();
        if (task != null) {
            int taskResult = task.call();
            switch (taskResult) {
                case (Task.INITIALIZE_STATE):
                    break;
                case (Task.PROCESS_STATE):
                    break;
                case (Task.TERMINATE_STATE): {
                    //queue.add(new InitializeTask());
                    Thread.currentThread().interrupt();
                    break;
                }
                default:
                    ;
            }
        }
        getOSEvents();
    }
}
WinUser.MSG msg = new WinUser.MSG();

private void getOSEvents() throws InterruptedException {
    if (isMac) {
        receiveEvents();
    } else {
        peekMessage(msg);
    }
}

Above, whenever I get my camera event, it add's it to the queue and in each loop I check the queue to process any Task. One more important information: This is a process running on cmd and has no window. I just need the events from my camera and nothing else.

The code where I register callback functions:

/**
 * Adds handlers.
 */
private void addHandlers() {
    EdSdkLibrary.EdsVoid context = new EdSdkLibrary.EdsVoid(new Pointer(0));
    int result = EDSDK.EdsSetObjectEventHandler(edsCamera, new NativeLong(EdSdkLibrary.kEdsObjectEvent_All), new ObjectEventHandler(), context).intValue();
  //above ObjectEventHandler contains a function "apply" which is set as callback function

    context = new EdSdkLibrary.EdsVoid(new Pointer(0));
    result = EDSDK.EdsSetCameraStateEventHandler(edsCamera, new NativeLong(EdSdkLibrary.kEdsStateEvent_All), new StateEventHandler(), context).intValue();
   //above StateEventHandler contains a function "apply" which is set as callback function


    context = new EdSdkLibrary.EdsVoid(new Pointer(0));
    result = EDSDK.EdsSetPropertyEventHandler(edsCamera, new NativeLong(EdSdkLibrary.kEdsStateEvent_All), new PropertyEventHandler(), context).intValue();
 //above PropertyEventHandler contains a function "apply" which is set as callback function

}
like image 609
Jatin Avatar asked May 09 '13 11:05

Jatin


1 Answers

You are getting ALL messages from ALL windows that belong to this thread, that includes all mouse moves, paints etc. if you aren't rapidly calling this function your message queue will overflow and cause the behavior you describe.

The sleep you definitely don't want as GetMessage yields if no message is waiting.

So if there exists a normal message pump(s) (i.e GetMessage/DispatchMessage) loop somewhere else for this threads window(s) then you should let that pump do most of the work, perhaps use wMsgFilterMin, wMsgFilterMax to just get the event message you require; or even better in this case use peekmessage with PM_NOREMOVE (then you will need your sleep call as peekmessage returns immediately).

Alternatively provide the hWnd of the window that generates the event to reduce the workload.

Use spy++ to look into which windows this thread owns and what messages are being produced.

To take this answer further please provide answers to: what else is this thread doing and what windows does it own; also is this message pump the only one or do you call into the SDK API where it may be pumping messages too?

like image 95
slonik Avatar answered Nov 12 '22 19:11

slonik