我正在使用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
}
答案 0 :(得分:1)
您正在从属于此线程的所有窗口获取所有消息,包括所有鼠标移动,颜料等。如果您没有快速调用此函数,您的消息队列将溢出并导致您描述的行为。
如果没有消息在等待,那么你绝对不想要的睡眠因为GetMessage会产生。
因此,如果存在一个正常的消息泵(即GetMessage / DispatchMessage)循环到此线程窗口的其他地方那么你应该让那个泵完成大部分工作,也许使用wMsgFilterMin,wMsgFilterMax来获取您需要的事件消息;或者更好的是在这种情况下使用peekmessage和PM_NOREMOVE(那么你需要睡觉 呼叫peekmessage立即返回。)
或者提供生成事件的窗口的hWnd以减少工作量。
使用spy ++查看此主题所拥有的窗口以及正在生成的消息。
为了进一步得到这个答案,请提供以下答案:该线程还在做什么以及它拥有哪些窗口;也是这个消息泵是唯一的一个,还是你调用SDK API,它也可能在传输消息?
答案 1 :(得分:0)
有一个OpenSource项目用EDNA包装EDSDK,它有一个代码版本可能更好用:
https://github.com/kritzikratzi/edsdk4j/blob/master/src/edsdk/api/CanonCamera.java#L436
不幸的是,这不是平台独立的,特别是在Windows上工作的方式。我目前正在尝试获得MacOS版本的工作: