java 在异步回调中捕获异常
java Catch exception inside a async callback
我有一个可能会抛出自定义异常的回调。
我试图抛出它,但它没有被外部作用域捕获,编译器也没有让我捕获它,它说:“Exception is never thrown is the corresponding try block”,即使它是。
这是我的代码:
public void openAsync(MessageAsyncCallback callback) {
try {
this.sendChannelOpen(this.getChannel(), getChannelOpenData().getFlags(), new MessageAsyncCallback() {
@Override
public void onComplete() throws NanoException {
// INanoPacket message = transport.getMessageByClassName(AudioServerHandshake.class.getName());
INanoPacket message = transport.getMessageByClassName(AudioClientHandshake.class.getName());
Log.info("Got audio server handshake, trying to client-handshake it");
sendClientHandshakeAsync((AudioServerHandshake) message, callback);
}
});
} catch (NanoException e) {
System.exit(-2);
}
}
它不让我抓到 NanoException
编辑:
在 transport.getMessageByClassName
里面我扔了一个 NanoException
.
编辑2:
这是调用异常的方法:
public INanoPacket getMessageByClassName(String destClassName) throws NanoException {//} throws NanoException {
long startTime = System.currentTimeMillis(); // fetch starting time
INanoPacket message = this.getMessageFromTCPQueue();
while (!(message.getClass().getName().equals(destClassName)) && isRuntimeValid(startTime)) {
this.insertToTCPQueue(message); // put message back in queue
message = this.getMessageFromTCPQueue();
}
if (!(message.getClass().getName().equals(destClassName))) {
// timeout...
throw new NanoException("Couldn't find destination message: " + destClassName);
}
return message;
}
我什至不想在 openAsync
中处理异常,而是在调用 openAsync
的方法中处理异常。
为什么? 因为我正在处理来自远程设备的消息,所以它是异步的。我正在使用某种超时来等待特定消息,如果消息没有出现,我想重新启动整个程序。
请注意,在您的代码中您没有调用 onComplete
方法,而是定义了它。
异常将在代码的单独部分中抛出,可能是单独的 Thread
(因为它似乎是异步的)。因此,“永远不会抛出异常是相应的 try 块”消息是正确的,因为调用 this.sendChannelOpen(...)
方法时永远不会抛出异常。
您的 try-catch
语句需要包装您调用 onComplete
方法的地方。因为只有调用 onComplete
方法,你才能期望 NanoException
.
根据评论进行编辑:
如果你需要处理 getMessageByClassName
中抛出的异常,你可以在 onComplete
方法中处理,而不是重新抛出它。如果您想在其他地方处理它,您需要向我们提供 sendChannelOpen
方法的代码或调用回调的地方。
EDIT2(基于问题编辑):
请参阅下面的代码,作为如何在线程之间进行通信的示例。我用过 Latch,但 java.util.concurrent 中还有其他 类 可能对您有用。
顺便说一句,我不会讨论为什么要在 NanoException 上重新启动整个应用程序,尽管可能还有其他值得考虑的选项来从该异常中恢复。
import java.util.concurrent.CountDownLatch;
class NanoException extends Exception {}
interface MessageAsyncCallback {
void onComplete() throws NanoException;
}
public class AsyncApp {
private static final CountDownLatch errorLatch = new CountDownLatch(1);
public static void main(String[] args) {
new AsyncApp().run();
}
void run() {
sendChannelOpen("something", new MessageAsyncCallback() {
@Override
public void onComplete() throws NanoException {
// the whole try-catch-sleep is not really needed, just to wait a bit before exception is thrown
try {
// not needed, just to wait a bit before exception is thrown
Thread.sleep(5000);
} catch (InterruptedException e) {
throw new NanoException();
}
throw new NanoException();
}
});
try {
System.out.println("This is a main thread and we wait here, while the other thread executes...");
errorLatch.await();
System.out.println("Latch has reached 0, will now exit.");
System.exit(-2);
} catch (InterruptedException e) {
System.out.println("Error in main thread.");
System.exit(-1);
}
}
void sendChannelOpen(String notImportant, MessageAsyncCallback troublesomeCallback) {
runSomethingInSeparateThread(troublesomeCallback);
}
void runSomethingInSeparateThread(MessageAsyncCallback troublesomeCallback) {
new Thread(() -> {
try {
troublesomeCallback.onComplete();
} catch (NanoException e) {
System.out.println("You can catch it here, and do system exit here or synchronize with main Thread as below");
errorLatch.countDown();
}
}).start();
}
}
我有一个可能会抛出自定义异常的回调。 我试图抛出它,但它没有被外部作用域捕获,编译器也没有让我捕获它,它说:“Exception is never thrown is the corresponding try block”,即使它是。
这是我的代码:
public void openAsync(MessageAsyncCallback callback) {
try {
this.sendChannelOpen(this.getChannel(), getChannelOpenData().getFlags(), new MessageAsyncCallback() {
@Override
public void onComplete() throws NanoException {
// INanoPacket message = transport.getMessageByClassName(AudioServerHandshake.class.getName());
INanoPacket message = transport.getMessageByClassName(AudioClientHandshake.class.getName());
Log.info("Got audio server handshake, trying to client-handshake it");
sendClientHandshakeAsync((AudioServerHandshake) message, callback);
}
});
} catch (NanoException e) {
System.exit(-2);
}
}
它不让我抓到 NanoException
编辑:
在 transport.getMessageByClassName
里面我扔了一个 NanoException
.
编辑2: 这是调用异常的方法:
public INanoPacket getMessageByClassName(String destClassName) throws NanoException {//} throws NanoException {
long startTime = System.currentTimeMillis(); // fetch starting time
INanoPacket message = this.getMessageFromTCPQueue();
while (!(message.getClass().getName().equals(destClassName)) && isRuntimeValid(startTime)) {
this.insertToTCPQueue(message); // put message back in queue
message = this.getMessageFromTCPQueue();
}
if (!(message.getClass().getName().equals(destClassName))) {
// timeout...
throw new NanoException("Couldn't find destination message: " + destClassName);
}
return message;
}
我什至不想在 openAsync
中处理异常,而是在调用 openAsync
的方法中处理异常。
为什么? 因为我正在处理来自远程设备的消息,所以它是异步的。我正在使用某种超时来等待特定消息,如果消息没有出现,我想重新启动整个程序。
请注意,在您的代码中您没有调用 onComplete
方法,而是定义了它。
异常将在代码的单独部分中抛出,可能是单独的 Thread
(因为它似乎是异步的)。因此,“永远不会抛出异常是相应的 try 块”消息是正确的,因为调用 this.sendChannelOpen(...)
方法时永远不会抛出异常。
您的 try-catch
语句需要包装您调用 onComplete
方法的地方。因为只有调用 onComplete
方法,你才能期望 NanoException
.
根据评论进行编辑:
如果你需要处理 getMessageByClassName
中抛出的异常,你可以在 onComplete
方法中处理,而不是重新抛出它。如果您想在其他地方处理它,您需要向我们提供 sendChannelOpen
方法的代码或调用回调的地方。
EDIT2(基于问题编辑): 请参阅下面的代码,作为如何在线程之间进行通信的示例。我用过 Latch,但 java.util.concurrent 中还有其他 类 可能对您有用。 顺便说一句,我不会讨论为什么要在 NanoException 上重新启动整个应用程序,尽管可能还有其他值得考虑的选项来从该异常中恢复。
import java.util.concurrent.CountDownLatch;
class NanoException extends Exception {}
interface MessageAsyncCallback {
void onComplete() throws NanoException;
}
public class AsyncApp {
private static final CountDownLatch errorLatch = new CountDownLatch(1);
public static void main(String[] args) {
new AsyncApp().run();
}
void run() {
sendChannelOpen("something", new MessageAsyncCallback() {
@Override
public void onComplete() throws NanoException {
// the whole try-catch-sleep is not really needed, just to wait a bit before exception is thrown
try {
// not needed, just to wait a bit before exception is thrown
Thread.sleep(5000);
} catch (InterruptedException e) {
throw new NanoException();
}
throw new NanoException();
}
});
try {
System.out.println("This is a main thread and we wait here, while the other thread executes...");
errorLatch.await();
System.out.println("Latch has reached 0, will now exit.");
System.exit(-2);
} catch (InterruptedException e) {
System.out.println("Error in main thread.");
System.exit(-1);
}
}
void sendChannelOpen(String notImportant, MessageAsyncCallback troublesomeCallback) {
runSomethingInSeparateThread(troublesomeCallback);
}
void runSomethingInSeparateThread(MessageAsyncCallback troublesomeCallback) {
new Thread(() -> {
try {
troublesomeCallback.onComplete();
} catch (NanoException e) {
System.out.println("You can catch it here, and do system exit here or synchronize with main Thread as below");
errorLatch.countDown();
}
}).start();
}
}