我是JavaFX 2中的新手,我在JavaFX中使用多线程时遇到了一些麻烦。我面临的问题是应用程序只是冻结,我找不到原因。我相信在某些地方存在竞争条件,但我无法找到它。 正如JavaFx的文档所说,我创建了一个扩展“Service”的类,我用“start()”运行它:
public class ProcessadorTarefas extends Service<StatusRetorno>{
private final ITarefa tarefaPadrao=new TarefaVerificarImpressora();
private final ITarefa tarefa;
protected Logger logger = LoggerFactory.getLogger(this.getClass());
public ProcessadorTarefas(ITarefa tarefa) {
this.tarefa = tarefa;
}
public void processar() {
if(getState()==State.READY)
start();
else
restart();
}
@Override
protected Task<StatusRetorno> createTask() {
return new Task<StatusRetorno>() {
@Override
protected StatusRetorno call() throws Exception {
/*THE CODE FREEZES HERE*/
StatusRetorno status = tarefaPadrao.processar();
if (status == StatusRetorno.SUCESSO)
status = tarefa.processar();
return status;
}
};
}
}
调用“processar”方法的类侦听ProcessadorTarefas类的onSuceed,onCancelled和onFailed:
public abstract class ControladorBase implements IProcessamentoDispatcher, EventHandler<WorkerStateEvent> {
@Autowired
protected ControladorDialogoMensagem dialogoMensagem;
protected ITarefa tarefa;
protected String mensagem;
protected Set<IProcessamentoListener> listeners = new ConcurrentSkipListSet<IProcessamentoListener>();
protected void executarTarefa(ITarefa tarefa) {
executarTarefa(tarefa, null);
}
protected void executarTarefa(ITarefa tarefa, String mensagem) {
this.tarefa=tarefa;
this.mensagem=mensagem;
despacharProcessamento(StatusProcessamento.INICIADO, null);
final ProcessadorTarefas processador=new ProcessadorTarefas(tarefa);
processador.setOnSucceeded(this);
processador.setOnCancelled(this);
processador.setOnFailed(this);
processador.processar();
}
@Override
public void handle(WorkerStateEvent evento) {
StatusRetorno status= (StatusRetorno) evento.getSource().getValue();
despacharProcessamento(StatusProcessamento.FINALIZADO,status);
if(status==StatusRetorno.SUCESSO)
exibirMensagemSucesso();
else
exibirMensagemErro(status);
}
/*UNIMPORTANT CODE*/
private void despacharProcessamento(StatusProcessamento statusProcessamento, StatusRetorno statusRetorno) {
for (IProcessamentoListener listener : listeners)
listener.processamento(new EventoProcessamento(this, statusProcessamento,statusRetorno));
}
/*ADD AND REMOVE LISTENERS CODE*/
}
当代码在“call”方法上冻结时,不会调用侦听器并且不显示主对话框,因为在用户登录后调用此代码。
已添加信息
在关闭登录对话框之后和主对话框打开之前执行此代码,因此,屏幕中没有任何javafx元素:
public class App extends Application implements IDadosSubmetidosListener, IProcessamentoListener {
/*variable declaration ommited*/
public static void main(String args[]) {
launch(args);
}
@Override
public void start(Stage stage) throws Exception {
ApplicationContext contexto = new ClassPathXmlApplicationContext("/spring/appContext.xml");
App aplicacao = contexto.getBean(App.class);
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_GLOBAL);
aplicacao.iniciar();
}
private void iniciar() {
cancelarOperacoesTEF();
controladorDialogoLogin.adicionarListener(this);
/*opens login dialog*/
controladorDialogoLogin.abrir();
}
private void verificarDadosEAbrirTelaPrincipal() {
/*after the user logged in, close login dialog*/
controladorDialogoLogin.limparListeners();
controladorDialogoLogin.fechar();
if (verificadorFuncaoUsuario.usuarioAutorizado()) {
if (verificadorFuncaoUsuario.usuarioCaixa())
verificarSeECFValidoECadastrar();
else
controladorDialogoPrincipal.abrir();
} else {
controladorDialogoMensagem.adicionarListener(this);
controladorDialogoMensagem.exibirAlerta("Você não tem credenciais que te permitam acessar este sistema!");
}
}
private void verificarSeECFValidoECadastrar() {
verificadorNumeroSerieECF.adicionarListener(this);
/*this code call that class shown above*/
verificadorNumeroSerieECF.verificarNumeroSerieECF();
}
private void terminarCadastroECFEAbrirTelaPrincipal() {
controladorDialogoCadastroECF.limparListeners();
controladorDialogoCadastroECF.fechar();
controladorDialogoPrincipal.abrir();
}
}
如您所见,代码在主线程中调用,这是调用该代码的正确位置,还是应该从对话框中调用它?
答案 0 :(得分:0)
我不知道Service类只有在从JavaFX组件调用时才有效。因此,为了解决这个问题,我将这部分代码调整为在单个线程中运行。在程序的其他部分,服务是从JavaFX的组件(例如一个按钮)启动的,它运行良好。