Eclipse Jobs stay in the Progress View after returning an OK status - eclipse

I have a an Eclipse Job class similar to the following:
public class MyCustomJob extends Job {
#Override
protected IStatus run(IProgressMonitor monitor) {
MyObject.blockingMethod();
return Status.OK_STATUS;
}
}
When I execute this job and it exits correctly, the bottom-right where the progress is listed while it is running still shows the name of the now completed job, but without any progress bar.
If I double click in the region where the name of the job still is, the Progress View opens as expected, but shows that the job has finished. If I click the "x" to clear the job, it disappears from the view, but if I close the view and reopen it, it comes right back.
How can I remove the name of the job from the bottom-right of the display and guarantee that if I clear the Finished job from the Progress View that is actually being dismissed?

Check the return path for any async UI execs that could affect status. Changing
from:
Platform.getDefault().asyncExec(runnable)
to
Platform.getDefault().syncExec(runnable)
fixed this issue

Related

What is the difference between .onAppear() and .task() in SwiftUI 3?

It seems we can now perform same task within .onAppear() or .task in iOS15. However could not find the advantage of .task() over .onAppear(). Anyone out there can explain?
Both task() and onAppear() are the same for running synchronous functions when a view appears.
The main point difference is in the task(id:priority:_:) task will be cancelled when this view disappears. It means when you're calling any webservice/ API or added any other task and back the screen then this task will automatically cancel.
Task is executed asynchronously and allowing you to start asynchronous work as soon as the view is shown.
Another use of task is, you can use task(id:_:)
as mention in the doc
The running task will be cancelled either when the value changes causing a new task to start or when this view disappears.
The example below shows listening to notifications to show when a user signs in.
Text(status ?? "Signed Out")
.task(id: server) {
let sequence = NotificationCenter.default.notifications(
of: .didChangeStatus, on: server)
for try await notification in sequence {
status = notification.userInfo["status"] as? String
}
}
You can read more from this article.

How to get ACRA to stop app when exception is not in main activity?

I want my app to stop when ACRA detects and reports an uncaught exception - normal ACRA behavior. This is not working when the exception happens in an activity that is not the main activity.
After fighting this in my actual app, I created a very simple app that uses ACRA, and allows me to force an exception in either the main activity, or a second one that can be started from the first. I am testing with a MinSDK of 26. The app is in Java and has only enough code to generate this test.
An exception in the first activity produces the desired result (as determined from logcat and the screen):
On button touch, main activity generates an exception
ACRA catches the exception:
ACRA starts another application process
the first process ends
the second process does ACRA processing
the second process ends
However, running again, but with the exception in the second activity (with the first still on the task stack), results in:
On button touch, main activity starts second activity
On button touch, second activity generates an exception
ACRA starts another application process
First process ends
ACRA processes in the second process (also using this code base)
meanwhile Android starts yet a third process - this is the problem
The second process finishes
The third process displays the main activity screen, and waits
What seems to be happening is that Android is detecting that there is an activity left on the stack, and is starting a new process to bring that one forward.
But, ACRA should be stopping this.
Is this an ACRA problem? In any case, ideas on how to prevent it?
*NOTE:
In my tests, I am using touch events on a bottom navigation bar to generate a divide by zero exception.
The order of when ACRA finishes and the third process starts is indeterminate, as far as I can tell. It is also probably irrelevant.
Test results are from watching the screen, and logcat. Important evens are logged using the Log class.
Below is a snippet from the main activity that shows the button processing, and the exception generation. The second activity is similar.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Context context = this.getApplicationContext();
setContentView(R.layout.activity_main);
Log.i(MyApp.TAG, "MainActivity.onCreate() - pid:"+android.os.Process.myPid());
mTextMessage = findViewById(R.id.message);
BottomNavigationView navigation = findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener((item) -> {
switch (item.getItemId()) {
case R.id.navigation_home:
int i = 0;
Log.i(MyApp.TAG, "Throwing exception in main activity");
Log.i(MyApp.TAG, "This shouldn't show up" + 3 / i);
return true;
case R.id.navigation_dashboard:
Log.i(MyApp.TAG, "Starting Activity2");
startActivity(new Intent(context, Activity2.class));
return true;
case R.id.navigation_notifications:
mTextMessage.setText(R.string.title_notifications);
return true;
}
return false;
});
This is a bug in ACRA, fixed by this PR, which will be included in the next release (5.3.0).

MVVM, wait cursor while opening "slow" page

I have MVVM application with multiple pages. My all pages have ReadCommand() bound with:
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<i:InvokeCommandAction Command="{Binding ReadCommand}" CommandParameter="{Binding}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
This is my Read() command in ViewModel:
private void Read(object parameter)
{
HwDevice Device = new HwDevice();
this.Alarms = Device.Alarms; // this is slow (reading data from RS232 device)
Device.Dispose();
}
One page has slow data source and my application is frozen when this page is being loaded (about 5 seconds).
I want to set wait cursor on whole window, but I don't know how to do it in MVVM (Im MVVM newbie). Do I have to pass window reference by command parameter and set Wait cursor in command? If I should - how can I do it in XAML?
The problem is that the thread where you are going to execute your operation, is the same where your UI live. It's here that the BackgroundWorker come in handy.
BackgroundWorker bw = new BackgroundWorker();
bw.RunWorkerAsync += bw_DoWork;
bw.ProgressChanged += bw_ProgressChanged;
bw.RunWorkerCompleted += bw_WorkDone
The previous part was the declaration. Now you need to implement the events, but first modify Read method
private void Read(object parameter)
{
bw.RunWorkerAsync(parameter);
// put your logic here
}
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
object parameter = e.Argument;
}
Now that the logic is placed on another thread, you can use the progressChanged method to do various stuff. Like showing a progress bar to report the status, or simply enable or disable your wait cursor.
EDIT: You don't need to pass the bw to the UI. If you are using MVVM (like you should and you are doing) you can use bindings and event at your advantage, or implement an interface like this one. The point of the whole thing is that the UI is just "informed" that something on the background is going on, avoiding to freeze the main thread. You just need to decide how to display it. So it can be either using a wait cursor, or implementing a progress bar.

Eclipse Plugin Cancel Completely

When in an eclipse plugin you implement Job and Override the run()-method, you can make changes to the parameter IProgressMonitor and skip tasks if the user pushed Cancel like this:
if (!monitor.isCanceled()){
monitor.subTask("Doing stuff");
//do task
} else {
returnedStatus = Status.CANCEL_STATUS;
}
But that means that at least the currently active task has to be finished before skipping the rest. Is there any way to completely abort the plugin activity and execute a finally block when the user pushes cancel, without waiting for the next if (!monitor.isCanceled()) and without subdividing your whole program into subTasks?
No. Your Job has to be the one to react to cancellation, so you need to either break the job up into tasks for which you can report progress with worked() and check cancellation, or you have to send around sub-progressmonitors and do the same thing.
https://eclipse.org/articles/Article-Progress-Monitors/article.html

how to update/refresh Progress View from a long-running non-UI Job in eclipse rcp

i have a long-running non-UI Job with a number of sub-tasks. each sub-task updates caption for the Job's progress entry in the Progress View via IProgressMonitor.subTask(some-caption). the Job goes through three sub-tasks before it contributes to the UI in its fourth sub-task (via Display.syncExec() of course) by creating a new IEditorPart instance. the problem is that those initial three sub-tasks are never reflected in the Job's progress entry in the Progress View. in fact, the Job progress entry never actually appears in the Progress View until fourth sub-task. this, of course, creates a problem for a user who is left to wonder if anything is even happening. my guess is that once the Job starts, the vm thread "broker" (sorry, not well versed in this matter) never gets a chance to switch from a non-UI Job thread to the UI thread until the former actually makes a call to the latter via Display.syncExec(). my only solution at this point is to put Job thread to sleep for about half a second right after each sub-task kicks in, thereby allowing UI thread to take over long enough to update Progress View. and while this has worked most of the time, i still get instances here and there where the Porgress View still remains empty until fourth sub-task, leading me to believe that my solution is not of a robust kind. hence, i am looking for a robust one. thank you for your time!
EDIT: example code
Job job = new Job("multipleTasks") {
public IStatus run(IProgressMonitor monitor) {
monitor.beginTask("multiple tasks", IProgressMonitor.UNKNOWN);
monitor.subTask("task1");
monitor.worked(1);
try { Thread.sleep(1000); } catch (Exception e) { }
monitor.subTask("task2");
monitor.worked(1);
try { Thread.sleep(1000); } catch (Exception e) { }
monitor.subTask("task3");
monitor.worked(1);
try { Thread.sleep(1000); } catch (Exception e) { }
monitor.done();
return Status.OK_STATUS;
}
};
job.schedule();