SwingWorker在计算过程中仍会导致无响应的UI

时间:2014-12-01 00:22:38

标签: java neural-network

我正在编写一个UI,它启动SwingWorker来调用一些外部库函数,特别是来自neuroph library,以模拟神经网络。在SwingWorker我要么生成Genome s的群体,要么我通过遗传算法运行一些群体来找到最好的Genome s。

工作人员生成初始人口并返回足够快,以至于在SwingWorker.process调用SwingWorker之前,我无法判断对SwingWorker.done的调用是否已完成。虽然通过遗传算法运行群体会导致UI冻结直到它完成(目前不允许我进一步测试)。使用遗传算法逻辑时,不会向UI发送.process条消息,直到完成为止。

我还注意到,库会为实例化的神经网络生成的每个LearningEvent写入标准输出。因此,当SwingWorker正在处理神经网络的群体时,会产生“吨”(每个网络学习和测试3行)的输出。 这是否会导致将.process次呼叫备份回用户界面?

有没有办法迫使SwingWorker等待其所有.process消息都被UI发送和接收?

以下是SwingWorker

的代码示例
public class MLPEnvironment extends SwingWorker<Boolean, String>
{
    int gensRan = 0;
    boolean usingGA;
    DataSet envData;
    MainView mainView;
    LinkedList<Genome> population;
    EnvironmentParameters envParms;

    public MLPEnvironment(MainView inView, EnvironmentParameters inParms, LinkedList<Genome> inPop, DataSet inData)
    {
        envData = inData;
        mainView = inView;
        envParms = inParms;
        population = inPop;
        usingGA = envParms.evolveAtleastOneParameter();
    }

    // Main logic of worker
    @Override
    protected Boolean doInBackground() throws Exception
    {
        Boolean retVal = Boolean.TRUE;

        // Generate a initial population if this flag is set
        if(envParms.m_bGenerateInitPop)
        {
            newStatus("> Generating initial population...");
            generateInitialPopulation();
        }

        // If we are not just generating a population, but running the GA
        if(!envParms.m_bOnlyGenInitPop)
        {
            newStatus("> Running evolution on population...");
            startBigBang();
            newStatus("- Number of generations ran: " + gensRan);
        }
        // Otherwise just push the initial population to the UI for the user to see
        else
        {
            newStatus("> Pushing population to UI...");
            newStatus("ClearTable");
            for(int i = 0; i < population.size(); i++)
            {
                Genome curGen = population.get(i);
                String layerWidths = "";
                for(int j = 0; j < curGen.getLayerWidths().size(); j++)
                {
                    layerWidths += curGen.getLayerWidths().get(j).toString();
                    if(j != curGen.getLayerWidths().size()-1)
                        layerWidths += "-";
                }
                newStatus("NewRow" + GenomeFitnessResults.getResultsCSV(curGen) + curGen.getTFType() + "," + curGen.getLayerWidths().size() + "," + layerWidths + ",");
            }
            newStatus("- Done displaying initial population");
        }
        newStatus("Environment worker thread finished");

        return retVal;
    }

    // Generate the initial population
    private void generateInitialPopulation()
    {
        newStatus("  Initial population size: " + envParms.m_iInitPopSize);
        newStatus("  DataInSize: " + envData.getInputSize() + " DataOutSize: " + envData.getOutputSize());
        newStatus("  Trans: " + envParms.m_bEvolveTransferFunction + " Count: " + envParms.m_bEvolveHiddenLayerCount + " Widths: " + envParms.m_bEvolveHiddenLayerWidth);

        for(int i = 0; i < envParms.m_iInitPopSize; i++)
        {
            population.add(Genome.getGenomeFromParms(envParms));
        }
        newStatus("- Finished generating initial population");
    }

    // The start of the GA, the beininng of the networks "universe"
    private void startBigBang()
    {
        newStatus("  Using genetic algorithm: " + usingGA);
        newStatus("  Evaluating initial population...");
        population = Genome.evaluate(population, envData, envParms);
        newStatus("  Done evaluating initial population");

        if(usingGA)
        {
            newStatus("  > Starting genetic algorithm...");
            for(int i = 0; i < envParms.m_iNumGenerations; i++)
            {
                gensRan++;
                newStatus("    Generation: " + gensRan);
                population = Genome.select(population, envParms);
                population = Genome.crossOver(population, envParms);
                population = Genome.mutate(population, envParms);
                population = Genome.evaluate(population, envData, envParms);
            }
            newStatus("  - Genetic algorithm terminated");
        }

        newStatus("- Done running algorithm");
    }

    // Clean-up and closure after main process
    @Override
    protected void done() 
    {
        try 
        { 
            final Boolean retVal = get();
            mainView.environmentRunComplete(retVal, population);
        } 
        catch (InterruptedException ex) 
        {
            // Not sure who I can tell... 
            System.out.println("DC: InterruptedException");
            mainView.environmentRunComplete(Boolean.FALSE, null);
        } 
        catch (ExecutionException ex) 
        {
            // Not sure who I can tell... 
            System.out.println("DC: ExecutionException");
            mainView.environmentRunComplete(Boolean.FALSE, null);
        } 
    }


    // These are used to write updates to the main view
    private void newStatus(String arg)
    {
        publish(arg);
    }

    @Override
    protected void process(List<String> list) 
    {
        list.stream().forEach((line) -> { mainView.newStatusLine(line); });
    }
}
编辑:这是另一种方式。

我理解

publish("a");
publish("b", "c");
publish("d", "e", "f");

实际上可能会导致

process("a", "b", "c", "d", "e", "f")

被召唤。进程“批处理”进入UI时是否有任何已定义的时间间隔?当我用按钮启动swing工作器时,单击UI变得没有响应,但是库打印系统输出行,然后一旦完成所有swingworker计算,我就会在UI中看到所有调用newStatus

所以我知道工作人员正在做一些紧张的工作,但是为什么在所有工作完成后,在完成工作所需的几秒钟内,所有人都要调用newStatus?在执行密集型任务之前和之前,是否应该将某些发布调用发送到UI?

如果有的话,UI不应该保持响应,因为当摇摆工作者正在工作时,没有显示任何消息吗?

0 个答案:

没有答案