From 70ffedfb4af4379f265fea1d2919cebcdb8069e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=A4ubrich?= Date: Thu, 9 Jan 2025 12:39:11 +0100 Subject: [PATCH] Perform element changes always in a non UI thread Currently PackageExplorerContentProvider receives events for changed elements from different threads and already has handling to perform only certain actions in the UI thread. But it does not really account for the case when the event itself is triggered from the UI thread in which case lengthy operation can take place in the UI. This now checks if the change is using the UI and otherwise schedules a job to perform the required actions in the background. --- .../packageview/ContentProviderTests3.java | 12 +++++++++--- .../PackageExplorerContentProvider.java | 17 ++++++++++++++++- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/packageview/ContentProviderTests3.java b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/packageview/ContentProviderTests3.java index c6dcf4b94c1..f734612e368 100644 --- a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/packageview/ContentProviderTests3.java +++ b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/packageview/ContentProviderTests3.java @@ -30,6 +30,7 @@ import org.eclipse.jdt.testplugin.JavaTestPlugin; import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.jobs.Job; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; @@ -202,9 +203,14 @@ public void testDeleteBottomLevelFragmentFolding() throws Exception { //send a delta indicating fragment deleted IElementChangedListener listener= (IElementChangedListener) fProvider; IJavaElementDelta delta= TestDelta.createDelta(fPack4, IJavaElementDelta.REMOVED); - listener.elementChanged(new ElementChangedEvent(delta, ElementChangedEvent.POST_CHANGE)); - - //force events from dispaly + //using a job prevents running the update in the UI what would internally create a job so better use one we can control... + Job job= Job.create("ElementChangeTestJob", m->{ + listener.elementChanged(new ElementChangedEvent(delta, ElementChangedEvent.POST_CHANGE)); + }); + job.schedule(); + //wait for job + job.join(); + //force events from display while(fMyPart.getTreeViewer().getControl().getDisplay().readAndDispatch()) assertTrue(fMyPart.hasRefreshHappened(), "Refresh happened"); //$NON-NLS-1$ diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/packageview/PackageExplorerContentProvider.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/packageview/PackageExplorerContentProvider.java index 2e50c4ba7cc..0b38b0cdfef 100644 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/packageview/PackageExplorerContentProvider.java +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/packageview/PackageExplorerContentProvider.java @@ -28,6 +28,7 @@ import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; @@ -127,6 +128,20 @@ protected Object getViewerInput() { @Override public void elementChanged(final ElementChangedEvent event) { + IJavaElementDelta delta= event.getDelta(); + if (Display.findDisplay(Thread.currentThread()) == null) { + processDelta(delta); + } else { + Job job= Job.create(PackagesMessages.PackageExplorerContentProvider_update_job_description, m -> { + processDelta(delta); + return m.isCanceled() ? Status.CANCEL_STATUS : Status.OK_STATUS; + }); + job.setSystem(true); + job.schedule(); + } + } + + protected void processDelta(IJavaElementDelta delta) { final ArrayList runnables= new ArrayList<>(); try { clearPackageCache(); @@ -136,7 +151,7 @@ public void elementChanged(final ElementChangedEvent event) { if (inputDeleted(runnables)) return; - processDelta(event.getDelta(), runnables); + processDelta(delta, runnables); } catch (JavaModelException e) { JavaPlugin.log(e); } finally {