私はEclipse RCPアプリケーションを持っています。そして、このコマンドが実行されているときにコマンドがあります。スレッドを開始する必要があります。このスレッドの実行後、GUI を更新する必要があります。しかし、このスレッドまたは他の非 SWT スレッドは GUI を更新できないと思います。しかし、それは合理的なようです。私がそれをやろうとしていたとき、私は得Exception in thread "Thread-5" org.eclipse.swt.SWTException: Invalid thread access
ました。どうすればこの目標を達成できますか?
6 に答える
SWTを使用するには、GUIを更新するものをメインスレッドで実行する必要があります。Eclipseでは、UIスレッドと呼ばれます(同じスレッドです)。別のスレッドのSWTオブジェクトにアクセスしようとしているため、このエラーが発生します。Display.syncExec()
またはDisplay.asyncExec()
を使用して、SWT関連の処理をメインスレッドに移動することを検討してください。syncExec()
デッドロックを引き起こさないように注意する必要があります。
通常、RCP アプリケーションでは java.lang.Thread を使用しません。なぜなら、Eclipse はジョブ API ( https://eclipse.org/articles/Article-Concurrency/jobs-api ) を介して、さまざまなレベルの抽象化と長時間実行される操作の制御を提供するためです。 .html )。問題の解決策は次のとおりです。
Runnable uiUpdater = new Runnable() {
public void run() {
// update SWT UI safely here
// ...
}
};
Job longRunningOperation = new Job("My command") {
protected IStatus run(IProgressMonitor monitor) {
// some time consuming code here
// ...
Display.getDefault().asyncExec(uiUpdater);
return Status.OK_STATUS;
}
};
longRunningOperation.schedule();
バックグラウンドで何をする必要があるかにもよりますが、バックグラウンド タスクの実行とユーザーへのフィードバックの提供をサポートする Eclipse ジョブ API を参照することをお勧めします。「Eclipse ジョブ チュートリアル」を検索します。ここに良いものがあります: http://www.vogella.com/articles/EclipseJobs/article.html
非 UI スレッドから UI スレッドにアクセスしようとしているため、この例外が発生しています。使用するDisplay.syncExec()
かDisplay.asyncExec()
、問題を解決します。
Display.getDefault().asyncExec() または Display.getDefautl().syncExec() を使用する必要があります。
サンプルコード:
@PostConstruct
public void createControls(Composite parent) {
.... \\ label definition
}
public void updateInterface(String message)
{
try{
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
try{
label.setText(message);
}
catch(Exception exc){
System.out.println(exc);
}
}
});
}
catch(Exception exception){
System.out.println(exception);
}
}
SWT の世界で最も一般的な例外に直面しています! 無効なスレッド アクセスが意味することは 1 つだけです。つまり、GUI 要素を変更または単にアクセスしたいのに、GUI スレッドではないスレッドでそれを実行しているということです。
コードでボタンのクリックなどを行った場合には発生しませんが、バックグラウンド プロセスまたは非同期通知を使用している場合は常に発生します。
1 つの解決策があります: 特定のブロックでコードを実行します。
Display.getDefautl().syncExec(new Runnable() {
public void run() {
// code related to GUI element(s)
}
}
また
Display.getDefautl().asyncExec(new Runnable() {
public void run() {
// code related to GUI element(s)
}
}
最初のケースでは、実行は同期的です。呼び出しスレッドは、run メソッドが実行されるのを待ちます。2 番目のケースでは、呼び出しスレッドは待機していません。
Eclipse アプリケーションのスレッドの詳細については、デバッグ ビュー (デバッグ モード) でスタックを参照してください。Mainと呼ばれる最初のスレッドは UI スレッドです。