6

我正在使用 JNA 来访问User32函数(我认为这与 Java 无关,更多的是概念问题)。在我的应用程序中,我有一个与 Canon SDK 通信的 Java 进程。要发送任何消息,我使用以下函数:

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在循环中调用,一切正常。每当从相机拍摄图像时,我都会得到事件并完成其余的工作。

但是我观察到,在相机没有任何活动的大约 15 秒(有时从不或有时只是开始)之后,拍照不会给我任何下载事件。后来整个应用程序变得无法使用,因为它没有从相机中获取任何事件。

这可能是什么原因?请让我知道需要的任何其他信息,我可以粘贴相应的代码。

编辑:

初始化:

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);
    }
}

上面,每当我得到我的相机事件时,它都会将它添加到queue并且在每个循环中我检查queue处理任何Task. 一个更重要的信息:这是一个运行的进程cmd并且没有窗口。我只需要我的相机中的事件,没有别的。

我注册回调函数的代码:

/**
 * 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

}
4

2 回答 2

1

您将从属于该线程的所有窗口获取所有消息,包括所有鼠标移动、绘画等。如果您不快速调用此函数,您的消息队列将溢出并导致您描述的行为。

如果没有消息在等待,您绝对不想要 GetMessage 产生的睡眠。

因此,如果在此线程窗口的其他地方存在一个正常的消息泵(即 GetMessage/DispatchMessage)循环,那么您应该让该泵完成大部分工作,也许使用 wMsgFilterMin、wMsgFilterMax 来获取事件消息您需要;或者在这种情况下甚至更好地使用 peekmessage 和 PM_NOREMOVE (然后你将需要你的睡眠呼叫,因为 peekmessage 立即返回)。

或者提供生成事件的窗口的 hWnd 以减少工作量。

使用 spy++ 查看该线程拥有哪些窗口以及正在生成哪些消息。

为了进一步回答这个问题,请提供以下答案:这个线程还在做什么以及它拥有什么窗口;这个消息泵也是唯一的,还是您调用SDK API,它也可能在泵送消息?

于 2013-05-29T21:46:32.750 回答
0

有一个用 JNA 包装 EDSDK 的 OpenSource 项目,它的代码版本可能运行得更好:

https://github.com/kritzikratzi/edsdk4j/blob/master/src/edsdk/api/CanonCamera.java#L436

不幸的是,这不是平台独立的,特别是在 Windows 上的工作方式。我目前正在尝试获取 MacOS 版本的工作:

https://github.com/WolfgangFahl/edsdk4j

于 2016-08-14T08:25:15.390 回答