简体   繁体   English

Netty和JavaFX的“不在FX应用程序线程上”异常

[英]“Not on FX application thread” exception with Netty and JavaFX

I am creating a Netty/JavaFX application and i faced with a following exception when i try to send a picture from client to server. 我正在创建一个Netty / JavaFX应用程序,当尝试从客户端向服务器发送图片时遇到以下异常。

Exception in thread "nioEventLoopGroup-3-1" java.lang.IllegalStateException: Not on FX application thread; currentThread = nioEventLoopGroup-3-1
    at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:204)
    at com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:364)
    at javafx.scene.Scene.addToDirtyList(Scene.java:485)
    at javafx.scene.Node.addToSceneDirtyList(Node.java:424)
    at javafx.scene.Node.impl_markDirty(Node.java:415)
    at javafx.scene.Node.notifyParentsOfInvalidatedCSS(Node.java:8709)
    at javafx.scene.Node.requestCssStateTransition(Node.java:8639)
    at javafx.scene.Node.pseudoClassStateChanged(Node.java:8680)
    at javafx.scene.Node$FocusedProperty.markInvalid(Node.java:7535)
    at javafx.scene.Node$FocusedProperty.store(Node.java:7520)
    at javafx.scene.Node.setFocused(Node.java:7578)
    at javafx.scene.control.TableRow.updateFocus(TableRow.java:305)
    at javafx.scene.control.TableRow.lambda$new$58(TableRow.java:106)
    at javafx.scene.control.TableRow$$Lambda$197/862831050.invalidated(Unknown Source)
    at javafx.beans.WeakInvalidationListener.invalidated(WeakInvalidationListener.java:83)
    at com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:349)
    at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
    at javafx.beans.property.ReadOnlyObjectWrapper$ReadOnlyPropertyImpl.fireValueChangedEvent(ReadOnlyObjectWrapper.java:176)
    at javafx.beans.property.ReadOnlyObjectWrapper.fireValueChangedEvent(ReadOnlyObjectWrapper.java:142)
    at javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:112)
    at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:145)
    at javafx.scene.control.TableView$TableViewFocusModel.setFocusedCell(TableView.java:2981)
    at javafx.scene.control.TableView$TableViewFocusModel.focus(TableView.java:3022)
    at javafx.scene.control.TableView$TableViewSelectionModel.focus(TableView.java:1941)
    at javafx.scene.control.TableView$TableViewSelectionModel.focus(TableView.java:1935)
    at javafx.scene.control.TableView$TableViewSelectionModel.focus(TableView.java:1918)
    at javafx.scene.control.TableView$TableViewArrayListSelectionModel.clearSelection(TableView.java:2554)
    at javafx.scene.control.TableView$TableViewArrayListSelectionModel$3.onChanged(TableView.java:2036)
    at javafx.collections.WeakListChangeListener.onChanged(WeakListChangeListener.java:88)
    at com.sun.javafx.collections.ListListenerHelper$Generic.fireValueChangedEvent(ListListenerHelper.java:329)
    at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:73)
    at javafx.collections.ObservableListBase.fireChange(ObservableListBase.java:233)
    at javafx.collections.ListChangeBuilder.commit(ListChangeBuilder.java:482)
    at javafx.collections.ListChangeBuilder.endChange(ListChangeBuilder.java:541)
    at javafx.collections.ObservableListBase.endChange(ObservableListBase.java:205)
    at javafx.collections.ModifiableObservableListBase.remove(ModifiableObservableListBase.java:183)
    at network.ServerHandler.handlerRemoved(ServerHandler.java:53)
    at io.netty.channel.DefaultChannelPipeline.callHandlerRemoved0(DefaultChannelPipeline.java:527)
    at io.netty.channel.DefaultChannelPipeline.callHandlerRemoved(DefaultChannelPipeline.java:521)
    at io.netty.channel.DefaultChannelPipeline.remove0(DefaultChannelPipeline.java:351)
    at io.netty.channel.DefaultChannelPipeline.destroyDown(DefaultChannelPipeline.java:798)
    at io.netty.channel.DefaultChannelPipeline.destroyUp(DefaultChannelPipeline.java:767)
    at io.netty.channel.DefaultChannelPipeline.destroy(DefaultChannelPipeline.java:759)
    at io.netty.channel.DefaultChannelPipeline.fireChannelUnregistered(DefaultChannelPipeline.java:743)
    at io.netty.channel.AbstractChannel$AbstractUnsafe$6.run(AbstractChannel.java:615)
    at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:380)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:357)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:116)
    at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
    at java.lang.Thread.run(Thread.java:745)

This exception thrown when i launch my app as javafx application. 当我以javafx应用程序启动我的应用程序时抛出此异常。 When istart it as an console application, the client disconnect from the server but no error or exception shown. 当我将其作为控制台应用程序启动时,客户端与服务器断开连接,但未显示任何错误或异常。

Client handler: 客户端处理程序:

class ClientHandler extends ChannelInboundMessageHandlerAdapter<Object> {

    @Override
    public void messageReceived(ChannelHandlerContext ctx, Object msg) throws Exception {
        MessageWrapper message = (MessageWrapper) msg;
        System.out.println(message);
        switch (message.getHeader()) {
            case "IMG":
                takeAndSendScreenShot();
            default:;
        }
    }

    private void takeAndSendScreenShot() throws IOException {
//        try {
//            //originalImage = new Robot().createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));
//
//        } catch (AWTException ex) {
//            Logger.getLogger(ClientHandler.class.getName()).log(Level.SEVERE, null, ex);
//        }

        BufferedImage originalImage = ImageIO.read(new File("c:\\test.jpg"));
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(originalImage, "jpg", baos);
        baos.flush();
        byte[] imageInByte = baos.toByteArray();
        baos.close();
        Client.getChannel().write(new MessageWrapper("IMG", baos));
//      Client.getChannel().write(new MessageWrapper("TEST", "TEST"));

    }
}

server: public class Server { 服务器:公共类服务器{

private static final Logger log = Logger.getLogger(Server.class.getName());

private final int port;

public Server(int port) {
    this.port = port;
}

public void run() throws InterruptedException {
    EventLoopGroup mainGroup = new NioEventLoopGroup();
    EventLoopGroup slaveGroup = new NioEventLoopGroup();

    try {
        ServerBootstrap bootstarp = new ServerBootstrap()
                .group(mainGroup, slaveGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ServerInitaizer());
        bootstarp.bind(port).sync().channel().closeFuture().sync();
    } finally {
        mainGroup.shutdownGracefully();
        slaveGroup.shutdownGracefully();
    }
}

} Server init: }服务器初始化:

public class ServerInitaizer extends ChannelInitializer<SocketChannel> {

    @Override
    protected void initChannel(SocketChannel channel) throws Exception {
        ChannelPipeline pipeline = channel.pipeline();

//        pipeline.addLast("decoder", new ObjectDecoder(ClassResolvers.softCachingResolver(ClassLoader.getSystemClassLoader())));
        pipeline.addLast("decoder", new ObjectDecoder(ClassResolvers.weakCachingConcurrentResolver(ClassLoader.getSystemClassLoader())));
        pipeline.addLast("encoder", new ObjectEncoder());
        pipeline.addLast("handler", new ServerHandler());

    }
}

server handler: 服务器处理程序:

public class ServerHandler extends SimpleChannelInboundHandler<Object> {

    private static final Logger log = Logger.getLogger(Server.class.getName());

    private static final ChannelGroup channels = new DefaultChannelGroup(
            GlobalEventExecutor.INSTANCE);

    private static final ObservableList<Client> clients
            = FXCollections.observableArrayList(
                    (Client c) -> new Observable[]{c.userNameProperty(), c.remoteAddressProperty()});

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        log.info(ctx.toString());
        Channel incoming = ctx.channel();
        channels.add(incoming);
        clients.add(new Client(incoming.remoteAddress().toString(), ""));
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        Channel incoming = null;
        log.info(ctx.toString());
        try {
            incoming = ctx.channel();

            for (int i = clients.size() - 1; i > -1; i--) {
                if (incoming.remoteAddress().toString().equals(clients.get(i).getRemoteAddress())) {
                    clients.remove(i);
                }
            }
        } finally {
            channels.remove(incoming);
        }
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Object msg)
            throws Exception {
        log.info(msg.toString());
        Channel incoming = ctx.channel();
        MessageWrapper message = (MessageWrapper) msg;

        switch (message.getHeader()) {
            case "MSG":
                saveMessage(incoming, message.getContent().toString());
            case "USER":
                setUser(incoming, message.getContent().toString());
            default:;
        }
    }

Message wrapper: 消息包装器:

@Data
public class MessageWrapper implements Serializable{
    private static final long serialVersionUID = 1L;
    String header;
    Object content;

    public MessageWrapper(String message, Object content) {
        this.header = message;
        this.content = content;
    }


}

Main.java: Main.java:

public class Main extends Application {

    public static void main(String[] args) throws InterruptedException {
        launch(args);
        //new Server(8000).run();
    }

    @Override
    public void start(Stage stage) throws Exception {

        Task<Integer> task = new Task<Integer>() {
            @Override
            protected Integer call() {
                try {
                    new Server(8000).run();
                } catch (Exception e) {
                    System.out.println(e);
                }
                return 1;
            }
        };

        Thread th = new Thread(task);
        th.setDaemon(true);
        System.out.println("Starting server task...");
        th.start();

        Parent root = FXMLLoader.load(getClass().getResource("/fxml/TablePanel.fxml"));
        Scene scene = new Scene(root);
        stage.setTitle("FXML Welcome");
        stage.setScene(scene);
        stage.show();
    }

}

If anyone can tell me what is the problem or how can i get more information about this. 如果有人可以告诉我问题出在哪里,或者我如何获得有关此问题的更多信息。 I would really appraciate. 我会很感激。

You have an ObservableList which is used as a model for a JavaFX control, and you're updating that list from a Netty thread. 您有一个ObservableList,用作JavaFX控件的模型,并且正在从Netty线程更新该列表。 This causes JavaFX to attempt to update the UI from a Netty thread, which is not allowed (all UI operations need to be performed in the application thread). 这将导致JavaFX尝试从Netty线程更新UI,这是不允许的(所有UI操作都需要在应用程序线程中执行)。 You need to use Platform.runLater() to transfer execution to the application thread. 您需要使用Platform.runLater()将执行转移到应用程序线程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 JavaFX 不在 FX 应用程序线程上 - JavaFX not on FX application thread JavaFX中的Java AWT EventQueue“不在FX应用程序线程上”异常 - Java AWT EventQueue “Not on FX application thread” exception in JavaFX JavaFX和套接字=不在FX应用程序线程上 - JavaFX and Sockets = Not on FX application thread JavaFx 2.x-Swing:不在FX应用程序线程上 - JavaFx 2.x - Swing : Not on FX application thread Javafx使用计时器时不在fx应用程序线程上 - Javafx Not on fx application thread when using timer JavaFX:不在FX应用程序上发生线程错误 - JavaFX : Not on FX application thread error occurs JavaFX在FX Application线程之外的另一个线程中运行WebEngine - JavaFX Running WebEngine in another thread than FX Application Thread Javafx 具有多个 windows 的应用程序,适用于 2 个不同的用户。 错误不在 FX 应用程序线程上; - Javafx Application with multiple windows for 2 different users . error Not on FX application thread; 在 init() 中使用 JavaFX Alert 时出现 IllegalStateException 因为不在 FX 应用程序线程上 - IllegalStateException when using JavaFX Alert in init() because not on FX application thread JavaFX在jdk7上工作正常,但在jdk8上工作不正常:在FX应用程序线程上不工作 - JavaFX works fine on jdk7 but not on jdk8: Not on FX application thread
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM