在运行后台线程时更改javafx选项框会导致应用程序崩溃

时间:2018-03-01 16:04:26

标签: java multithreading javafx

我有一个设置窗口,其中包含两个选择框。一个用于选择音频接口,另一个用于选择该接口上的输入通道。

当选择第二个选项框中的项目时,将启动两个后台线程,一个打开targetdataline,另一个线程显示一个仪表以查看音频信号的电平。
这工作正常,但是当我在选择框上选择另一个音频接口时,我想要中断两个线程,保存设备更改,然后再次启动线程。目前,执行此操作会导致应用挂起,但不会报告任何错误。任何帮助表示赞赏。

我有一个对象'audio1Monitor',用于同步音频线程。音频线程在初始化时启动,并在调用此方法之前处于等待状态。我认为发生了两三种不同的错误。方法'captureAudio1()'是要在线程中运行的任务。这取决于两个选择框中每一个的对象。我使用Preferences API'systemPrefs'保存了这些 只有在线程运行时更改选项框对象时才会发生错误。我本质上想要停止captureAudio1()任务并让线程等待,同时selectbox事件监听器执行,然后在结束时通知线程恢复并启动captureAudio1()。有时我得到一个firevaluechangedevent错误,我读过这个错误通常是在选择一个对象时更改选项框的对象,所以尝试取消选择并清除第一个选择框监听器中的列表。我很清楚我在这里,并且已经把头发拉了好几天了。

第一个选择框的代码:

chan1interface.getSelectionModel().selectedIndexProperty().addListener(new ChangeListener<Number>(){
        @Override
        public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
            synchronized(capture.audio1Monitor){

                if (capture.audioInput1.getState().equals(RUNNING)){
                    capture.running = false;
                    try {
                        capture.audio1Monitor.wait();
                    } catch (InterruptedException ex) {
                        Logger.getLogger(ConfigController.class.getName()).log(Level.SEVERE, null, ex);
                    }
                } else {
                }

            Mixer.Info[] mixers = AudioSystem.getMixerInfo();
            Mixer m = AudioSystem.getMixer(mixers[chan1interface.getSelectionModel().getSelectedIndex()]);
            System.out.println(chan1interface.getSelectionModel().getSelectedItem());
            Line.Info[] lines = m.getTargetLineInfo();
            for (Line.Info info : lines){
                ArrayList channels = showSupportedChannels(info);
                System.out.println(channels);
                int maxValue = getMax(channels);
                ArrayList channelList = new ArrayList();
                    for (int i=0; i<maxValue; i++){
                        channelList.add(i+1);
                        }

                chan1channel.getSelectionModel().clearSelection();
                chan1channel.getItems().removeAll();
                ObservableList channelListOL = FXCollections.observableArrayList(channelList);
                chan1channel.setItems((ObservableList) channelListOL);
                }   
        String chan1Interface = m.getMixerInfo().getName();
        System.out.println(chan1Interface +" - chan1 interface");
        final String Interface1 = "interface1";
        systemPrefs.put(Interface1, chan1Interface);



            }

        }
    });

第二个选择框的代码:

chan1channel.getSelectionModel().selectedIndexProperty().addListener(new ChangeListener<Number>() {
        @Override
        public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue){
            synchronized(capture.audio1Monitor){
                capture.running = false;
                if (capture.audioInput1.isAlive()){
                    try {
                        capture.audioInput1.wait();
                    } catch (InterruptedException ex) {
                        Logger.getLogger(ConfigController.class.getName()).log(Level.SEVERE, null, ex);
                    }

                }


                chan1selectedchannel = (int) (chan1channel.getSelectionModel().getSelectedIndex()) + 1;
                Mixer.Info[] mixers = AudioSystem.getMixerInfo();
                Mixer m = AudioSystem.getMixer(mixers[chan1interface.getSelectionModel().getSelectedIndex()]);
                Line.Info[] lines = m.getTargetLineInfo();
                for (Line.Info info : lines){
                    ArrayList channels = showSupportedChannels(info);
                    System.out.println(channels);
                    chan1totalchannels = getMax(channels);
                }
                final String channel1selectedchannel = "chan1selectedchannel";
                final String chan1total = "chan1totalchannels";
                systemPrefs.put(channel1selectedchannel, String.valueOf(chan1selectedchannel));
                systemPrefs.put(chan1total, String.valueOf(chan1totalchannels));


            capture.running = true;

            System.out.println("4 is called");
            capture.audio1Monitor.notify();

            if (meterUpdate.isAlive() == false){
                try {
                    Thread.sleep(1000);
                    meterUpdate.start();
                } catch (InterruptedException ex) {
                    Logger.getLogger(ConfigController.class.getName()).log(Level.SEVERE, null, ex);
                }

            }
        }
    }
});

这是音频线程的代码:

Thread audioInput1 = new Thread(){
    public void run(){
        synchronized(audio1Monitor){
       System.out.println("audioInput1 thread started");
       while (constantLoop == true){
        try {

            System.out.println("audioInput1 'try' thread started");
            captureAudio1();
            System.out.println("audioInput1 Thread is waiting");
            audio1Monitor.wait();
            System.out.println("after waiting in thread");

        } catch (ParseException ex) {
            Logger.getLogger(audioIO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (LineUnavailableException ex) {
            Logger.getLogger(audioIO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InterruptedException ex) {
            try {
                audio1Monitor.wait();
            } catch (InterruptedException ex1) {
                Logger.getLogger(audioIO.class.getName()).log(Level.SEVERE, null, ex1);
            }
            System.out.println("after waiting in thread");
            Logger.getLogger(audioIO.class.getName()).log(Level.SEVERE, null, ex);
        } 
    }
    }
    }
};

仪表线程:

Thread meterUpdate = new Thread(new Runnable() {
public void run(){
    System.out.println("meter updating");
    try {
        Thread.sleep(2000);
    } catch (InterruptedException ex) {
        Logger.getLogger(ConfigController.class.getName()).log(Level.SEVERE, null, ex);
    }
    while (capture.running == true){
        int chunkDivision = 5;                                              //How much to divide each chunk into (total array / chunk division = SPL ms
        double[] localSPLArray = capture.chan1double;
        double sum1 = 0;
        for (int h=1; h<(chunkDivision+1); h++){
            long meterStart = System.currentTimeMillis();
            System.out.println("Start meter = " + System.currentTimeMillis());
        for (int i=0; i<(localSPLArray.length/chunkDivision); i++){
            sum1 += (Math.pow(Math.abs(localSPLArray[i + (chunkDivision*h)]), 2));
        }
        double RMS1sqrt = Math.sqrt(sum1/(localSPLArray.length/10));
        double RMS1;
        if (RMS1sqrt<5){
            RMS1 = 0.1;
        } else {
            RMS1 = 20*Math.log10(RMS1sqrt/(20*Math.pow(Math.E,-6)));
        }
        long meterStop = System.currentTimeMillis();
            try {
                double waitTime = (500/chunkDivision) - (meterStop-meterStart);
                System.out.println("WaitTime = " + waitTime);
                Thread.sleep((500/chunkDivision) - (meterStop-meterStart));
            } catch (InterruptedException ex) {
                Logger.getLogger(ConfigController.class.getName()).log(Level.SEVERE, null, ex);
            }
        Platform.runLater(() -> {

            chan1progressbar.setProgress(RMS1/90);

        });
     }
    }
});

0 个答案:

没有答案