【问题标题】:Reinvoke SwingWorker with another parameter value when the same previous SwingWorker is done当相同的前一个 SwingWorker 完成时,使用另一个参数值重新调用 SwingWorker
【发布时间】:2016-08-23 08:38:56
【问题描述】:

我使用了一个扩展 SwingWorker 的类,如下所示:

public class Analyzer extends SwingWorker<Integer, Object> {

  String source;
  public Analyzer(String simulation, DBConnector connection)
        throws ClassNotFoundException, SQLException, IOException {
    super();
    source=simulation;

    //creating several objects that get their data from a DB and will be "analyzed" in the background
  }

  @Override
  protected Integer doInBackground() {

    tripAnalyzer ta = new tripAnalyzer();
    if (trips.getIterator().hasNext()) {

        if (isCancelled()) {
            trips.close();
            ta.cancelFinish();
            return FAILED;
        }

        ta.init(null, null, false);

        while (trips.getIterator().hasNext()) {

            setProgress(trips.getProgress());
            ta.prepare(source, trips.getIterator().next());
        }
        //export the results to a text-file
        return SUCCESS;
    }    
  }
  @Override
  protected void done() {
    setProgress(100);
    trips.close();
    super.done();
  }
}

模拟的String值来自一个JTable。到目前为止,对于一个“模拟键”来说一切正常,但现在我想扩展它以便能够为几个“模拟键”做 Worker 的东西。 我想到的一种方法可能是使用模拟键传递一个数组或字符串列表,并适当地更改构造函数。但这将变得非常笨拙,因为我必须在构造函数的执行期间创建大量对象,并且要处理大量数据。我还可以专门为字符串数组创建一个单独的构造函数,但这将是大约 60 行代码的复制/粘贴,并且会出现结块问题。

我的想法是在对之前的模拟进行分析后,使用不同的模拟键重新实例化 Analyzer 类。 (是的,我知道在 EDT 期间多次实例化同一个 SwingWorker 不会多次调用 doInBackground 方法。但是一旦完成并摆脱困境,它应该可以工作......至少在我的脑海中:))。但是现在我碰壁了,真的不知道该怎么做。

工作流程应该是这样的:

1:我选择 f.ex。存储在数组或列表中的 JTable 中的 3 个模拟键 [1,2,3]

2:然后 Worker 从我的 GUI 类中实例化,并在第一个键(即 '1')上完成他的工作

3:在“1”上的工作完成后,工人应该被重新实例化并开始在“2”上工作

4:以此类推,直到处理完所有模拟密钥。

也许我的想法太僵硬了,有更好的方法来实现这一点,因此任何能帮助我指出正确方向的帮助都将不胜感激!谢谢

编辑

public Analyzer(String simulation, DBConnector connection){

    this(new String[]{simulation}, connection);
    source = simulation;
}

public Analyzer(String[] simulation, DBConnector connection){

    super();
    for( String s : simulation) this.simulations.add(s);
    this.connection = connection;
}

正如下面的 cmets 中所述,不需要 publish() 方法,因为状态栏会正确更新。

我放置所有键的列表是一个 LinkedList,它在每个循环周期中都会删除一个键,直到它为空。

【问题讨论】:

  • 为什么不循环遍历doInBackground()publish() 中的List&lt;Key&gt; 一个中间结果,因为每个都结束了?
  • @trashgod 事情是我继承了这个项目,我不想更改类的签名,因为最初编写它的人将所有 PreparedStatements 以及“trips”放在构造函数中目的。 I didn't want to create lets say 20 "trips" objects when 20 simulations are selected... One simulation consists of more than 2million households with more than 20million trips.我已经有了将所有内容放入“doInBackgroung()”的想法。但不幸的是,我也必须适应其他课程。
  • 对不起,如果我遗漏了什么,但实际的泛型参数Object 未使用;影响似乎很小。另请参阅approach 了解非顺序任务。
  • @trashgod 另一方面,我现在正在考虑将数据库内容放入doInBackground() 方法并设置2个构造函数......一个用于字符串变量,一个用于列表,让doInBackGround()处理剩下的。那可以解决。我应该把publish()方法放在哪里?在迭代块结束时?
  • @trashgod 它有效。我将所有繁重的 DB 代码放入 doInBackground() 方法中,并添加了一个额外的构造函数,该构造函数采用 StringArray。我会将其作为编辑放入帖子中。我什至不必打电话给publish()

标签: java swing


【解决方案1】:

我不得不稍微切换一下代码。前面我提到我不想更改类的签名......实际上我的意思是构造函数的签名,因为这个类被其他类实例化了。

在前一个构造函数(我继承了项目)中执行的整个 DB 操作已放入 doInBackground() 方法(它们实际上应该属于的地方),并且前一个构造函数已被重载,如下所述:Best way to handle multiple constructors in Java Craig P. Motlin 的回答

public Analyzer(String simulation, DBConnector connection){

    this(new String[]{simulation}, connection);
    source = simulation;
}

public Analyzer(String[] simulation, DBConnector connection){

    super();
    for( String s : simulation) this.simulations.add(s);
    this.connection = connection;
}

正如上面的 cmets 中提到的,publish() 方法不是必需的,因为状态栏会正确更新。

我放置所有键的列表是一个 LinkedList,它在每个循环周期中都会删除一个键,直到它为空。

所以最后程序中使用这个类的所有其他部分仍然可以正常工作,问题就解决了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-17
    • 1970-01-01
    • 2011-01-15
    • 1970-01-01
    • 2011-12-28
    相关资源
    最近更新 更多