如何链接多个SwingWorkers

huangapple go评论59阅读模式
英文:

How to chain multiple SwingWorkers

问题

我有一个大型的后台任务,其中需要一些中间步骤来获取用户输入。

例如,buttonLoad_actionPerformed --> 加载,验证有效性 --> 如果过时,询问用户是否要更新。如果是 --> 更新,如果否 --> 停止。

目前,我已经像这样编写了这段代码:

// 加载任务
SwingWorker<Status,Object> swLoad = new SwingWorker<>() {
    Validity doInBackground() {
        return load(file);
    }

    void done() {
        Validity validity = get();

        switch (validity) {
            case UPTODATE:
                return;
            case OUTDATED:
                int res = JOptionPane.showConfirmDialog("文件已过时。您是否要更新它?");
                if (res != JOptionPane.YES_OPTION) 
                    return;
                    
                // 更新任务
                SwingWorker<Boolean,Object> swUpdate = new SwingWorker<>() {
                    Boolean doInBackground() {
                        return update();
                    }

                    void done() {
                        Boolean success = get();
                        if (!success) ....
                    }
                };
                
                swUpdate.execute();
        }    
    }
};

swLoad.execute();

然而,如果需要多个步骤,这可能会变得难以阅读。

如何最好地链接条件/可选的 SwingWorkers ?

英文:

I've got a big background task with some intermediate points where a user input is required.

E.g. buttonLoad_actionPerformed --> load, verify validity --> if outdated, ask user whether to update. If yes --> update, if no --> stop.

For now, I've coded this like this:

// load worker
SwingWorker&lt;Status,Object&gt; swLoad=new SwingWorker&lt;&gt; () {
    Validity doInBackGround() {
        return load(file);
    }

    void done() {
        Validity validity=get();

        switch (validity) {
            case UPTODATE:
                return;
            case OUTDATED:
                int res=JOptionPane.showConfirmDialog(&quot;File obsolete. Do you want to update it ?&quot;);
                if (res != JOptionPane.YES_OPTION) 
                    return;
                    
                // update worker
                SwingWorker&lt;Boolean,Object&gt; swUpdate = new SwingWorker&lt;&gt;() {
                    Boolean doInBackGround() {
                        return update();
                    }

                    void done() {
                        Boolean success=get();
                        if (!success) ....
                    }
                };
                
                swUpdate.execute();
        }    
    }
};

swLoad.execute();

However this can be become pretty unreadable if multiple steps are required.

What's the best approach for chaining conditional/optional SwingWorkers ?

答案1

得分: 2

我不明白为什么你在你的 done 方法中做任何事情。

Validity doInBackGround() {
    Validity validity = load(file);
    switch (validity) {
        case UPTODATE:
            return validity;
        case OUTDATED:
            int res= confirmOnEdt();
            if (res == JOptionPane.YES_OPTION) {
                Boolean success = update();
                //检查更新并响应。
            }
    }
    return validity;
}

public int confirmOnEDT() throws InterruptedException{
    int[] container = {0};
    SwingUtilities.invokeAndWait( () -> {
            container[0] = JOptionPane.showConfirmDialog("文件已过时。您是否要更新它?");
        }
    );
    return container[0];
}

一个 SwingWorker 用于全部任务。JOptionPane 会阻塞你的后台线程并等待输入。此外,你可能希望返回与 Validity 不同的返回值。

英文:

I don't understand why you're doing anything in your done method.

Validity doInBackGround() {
    Validity validity = load(file);
    switch (validity) {
        case UPTODATE:
            return validity;
        case OUTDATED:
            int res= confirmOnEdt();
            if (res == JOptionPane.YES_OPTION) {
                Boolean success = update();
                //check the update and respond.
            }
    }
    return validity;
}

public int confirmOnEDT() throws InterruptedException{
    int[] container = {0};
    SwingUtilities.invokeAndWait( ()-&gt;{
            container[0] = JOptionPane.showConfirmDialog(&quot;File obsolete. Do you want to update it ?&quot;);
        }
    );
    return container[0];
}

One SwingWorker for the full set of tasks. The JOptionPane will block your background thread and wait for input. Also, you probably want to different return value than Validity.

答案2

得分: 0

鉴于这是一个有点晦涩的问题,我会试着回答。

有2个问题引起了我的注意:

  1. 所示的函数/方法相当冗长。
  2. 嵌套的层次很深。

改进这些问题的一个简单解决方案是将代码拆分为单独的方法。例如,将“OUTDATED”情况中的可操作代码移到一个单独的方法中。虽然这会使代码变长,但更容易理解。

public loadInWorker() {
    SwingWorker<Status,Object> swLoad = new SwingWorker<> () {
        Validity doInBackground() {
            return load(file);
        }

        void done() {
            onLoad(get());
        }
    };

    swLoad.execute();
}



private onLoad(Validity validity) {
    switch (validity) {
        case UPTODATE:
            return;
        case OUTDATED:
            int res = JOptionPane.showConfirmDialog("文件已过时。您要更新吗?");
            if (res == JOptionPane.YES_OPTION) {
                updateInWorker(); 
            }
    }
}



private updateInWorker() {
    SwingWorker<Boolean,Object> swUpdate = new SwingWorker<>() {
        Boolean doInBackground() {
            return update();
        }

        void done() {
            Boolean success = get();
            if (!success) {
                onUpdateFailure();
            }
        }
    };

    swUpdate.execute();
}



private onUpdateFailure() {
    // 这里是更新失败的代码
}

编辑 + 意见:
我要补充一下,我从未使用过这个worker API。看起来它似乎相当复杂。在我最后的Java开发日子里,我依赖于线程池来处理执行时间短的任务,并为执行时间长的任务使用专用线程。您还可以为SwingWorker调用编写一个包装器,因为您不关心它之外的内部类型。
以下是使用普通线程的示例:

public loadInThread() {
    new Thread(this::loadInThread, "Load Thread").start();
}



private loadInThread() {
    switch (load(file)) {
        case UPTODATE:
            return;
        case OUTDATED:
            int res = JOptionPane.showConfirmDialog("文件已过时。您要更新吗?");
            if (res == JOptionPane.YES_OPTION) {
                new Thread(this::updateInThread, "Update Thread").start();
            }
    }
}



private updateInThread() {
    if (!update()) {
        // 更新失败的代码放在这里
    }
}
英文:

Given that this is a bit of an obscure question, I'll give it a shot.

There are 2 items that stand out for me:

  1. The shown function/method is rather lengthy
  2. There is a lot of nesting going on

A simple solution to improve those is to split out code into separate methods.
Example, move the actionable code from the "OUTDATED" case into a separate method. Sure it's longer, but easier to follow.

public loadInWorker() {
	SwingWorker&lt;Status,Object&gt; swLoad=new SwingWorker&lt;&gt; () {
		Validity doInBackGround() {
			return load(file);
		}

		void done() {
			onLoad(get());
			}
		}
	};

	swLoad.execute();
}



private onLoad(Validity validity) {
	switch (validity) {
		case UPTODATE:
			return;
		case OUTDATED:
			int res=JOptionPane.showConfirmDialog(&quot;File obsolete. Do you want to update it ?&quot;);
			if (res == JOptionPane.YES_OPTION) {
				updateInWorker(); 
			}
	}
}



private updateInWorker() {
	SwingWorker&lt;Boolean,Object&gt; swUpdate = new SwingWorker&lt;&gt;() {
		Boolean doInBackGround() {
			return update();
		}

		void done() {
			Boolean success=get();
			if (!success) {
				onUpdateFailure();
			}
		}
	};

	swUpdate.execute();
}


private onUpdateFailure() {
	....
}

Edit + Opinion:
I'll add that I've never used that worker API. Looking at it, it seems quite convoluted. In my last days of Java development, I relied on ThreadPools for tasks with a short execution time and dedicated Threads for tasks with long execution time.
You could also write a wrapper for the SwingWorker call as you don't care about the internal types outside of it.
Example using bog standard Threads:

public loadInThread() {
	new Thread(this::loadInThread, &quot;Load Thread&quot;).start();
}


private loadInThread() {
	switch (load(file)) {
		case UPTODATE:
			return;
		case OUTDATED:
			int res=JOptionPane.showConfirmDialog(&quot;File obsolete. Do you want to update it ?&quot;);
			if (res == JOptionPane.YES_OPTION) {
				new Thread(this::updateInThread, &quot;Update Thread&quot;).start();
			}
	}
}



private updateInThread() {
	if (!update()) {
		// Update Failure code goes here
	}
}

huangapple
  • 本文由 发表于 2023年6月22日 19:17:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/76531334.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定