Задержка рабочего качания
У меня есть событие нажатия кнопки, которое запустит рабочий поток Swing, который, в свою очередь, запустит другой поток для выполнения длинных вычислений, включая запись файла. Затем этот файл читается для рисования графики. Однако часть рисования никогда не происходит, если я не добавляю задержку между ними... (Он говорит, что файл не найден, хотя файл там есть.. Какой лучший способ исправить это без добавления задержки..
private void buttonFragmentActionPerformed(java.awt.event.ActionEvent evt) {
try
{
ESIPlusFragmenterWorker epfw = new ESIPlusFragmenterWorker(10, sdfFile, cidSpectrum);
epfw.execute();
Thread.sleep(1000);
holder.molTable1.drawMolViewPanel(currDir+sep+"esiFragments"+sep+"esiFrag.sdf");
}
catch (Exception e)
{
e.printStackTrace();
}
}
Работник качели
public class ESIPlusFragmenterWorker extends SwingWorker<Void, Void>{
int mzppm_;
String SDF_;
String spectrum_;
Double mion_;
MolTable holder_;
ESIPlusFragmenterWorker(int mzppm, String SDF, String spectrum)
{
mzppm_ = mzppm;
SDF_ = SDF;
spectrum_ = spectrum;
}
@Override
protected Void doInBackground() {
try
{
Molecule mol;
MolImporter importer = new MolImporter(SDF_);
ExecutorService te = Executors.newFixedThreadPool(1);
while ((mol = importer.read()) != null)
{
Runnable epf = new ESIPlusFragmenter(mol, spectrum_, mzppm_);
Thread t = new Thread(epf);
te.execute(epf);
}
importer.close();
te.awaitTermination(10, TimeUnit.MINUTES);
}
catch (Exception e)
{
//
}
finally
{
return null;
}
}
@Override
protected void done() {
try {
//
} catch (Exception e) {
//e.printStackTrace();
}
}
}
1 ответ
Никогда, никогда, никогда не звони Thread.sleep(...)
на EDT, так как это приведет весь ваш графический интерфейс ко сну. И кроме того, что, если вы ошиблись, и фоновый процесс занимает больше времени, чем ваша задержка сна?
Одним из возможных решений является добавление PropertyChangeListener в SwingWorker и прослушивание свойства "state" для SwingWorker.StateValue, которое должно быть SwingWorker.StateValue.DONE, а затем выполните рисование.
например
private void buttonFragmentActionPerformed(java.awt.event.ActionEvent evt) {
try {
ESIPlusFragmenterWorker epfw = new ESIPlusFragmenterWorker(10,
sdfFile, cidSpectrum);
epfw.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent pcEvt) {
if ("state".equals(pcEvt.getPropertyName())) {
if (pcEvt.getNewValue().equals(SwingWorker.StateValue.DONE)) {
holder.molTable1.drawMolViewPanel(currDir + sep
+ "esiFragments" + sep + "esiFrag.sdf");
}
}
}
});
epfw.execute();
Таким образом, это ждет, пока SwingWorker завершит свою работу, прежде чем вызывать код внутри слушателя.
Другой вариант - вызвать ваш держатель.molTable1.drawMolViewPanel внутри SwingWorker's. done()
метод, и это тоже будет работать, но, как указано выше с PropertyChangeListener, SwingWorker не должен иметь никаких знаний о коде, вызываемом в слушателе (в отличие от использования SwingWorker done()
метод), и это может позволить более слабую связь.