This code does what I need, with the exception that there is a quick switch between the normal cursor, and the busy cursor happening extremely fast.
/* this code is run inside the createPartControl(Composite parent) method of a ViewPart */
Job job = new Job("refreshing")
{
#Override
protected IStatus run(IProgressMonitor monitor)
{
while (data.isReading())
{
Display.getDefault().syncExec(new Runnable()
{
#Override
public void run()
{
treeViewer.setInput(DataView.this.dataModel.getArray());
}
});
}
return Status.OK_STATUS;
}
};
job.schedule();
So is there a way of disabling the busy cursor of a Job in eclipse?
Also, could this happen because the Job is called in a GUI class?
Call
job.setSystem(true);
before you schedule the job. From the JavaDoc:
Sets whether or not this job is a system job. System jobs are
typically not revealed to users in any UI presentation of jobs. Other
than their UI presentation, system jobs act exactly like other jobs.
If this value is not explicitly set, jobs are treated as non-system
jobs. This method must be called before the job is scheduled.
However I think the busy cursor is coming from the BusyIndicator.showWhile call in AbstractTreeViewer.createChildren which the tree setInput will call. I don't think you can do anything about.
Related
I don't know if this is the best place to ask, but is it possible to query Quartz completed jobs ?
I can't find a solution, I already visited quartz website and googled it.
If you are looking for information on historical run like start, end time (duration), params with which it was invoked you need to create your own table to persist those information.
The way i have done this in the past is
Created a new JOB_LOG table
Created a Custom Quartz Job Listener by extending JobListenerSupport http://www.quartz-scheduler.org/api/2.1.7/org/quartz/listeners/JobListenerSupport.html
Depending on your requirement add your persistence logic to
#Override
public void jobToBeExecuted(JobExecutionContext context) {
//insert here
}
#Override
public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
//insert here
}
How do I create a Quartz Scheduler job that terminates automatically after given amount of time (if running job takes too much time)?
A Quartz scheduler has no built-in functionality to interrupt a job by itself after a given amount of time.
If you dont want to interrupt Jobs (see the interface InterruptableJob) manually (for example with rmi), you could easily establish such a automatically termination.
Either:
When starting a scheduler, fork a deamon-thread that runs periodically and checks whether some of the currently running jobs must be interrupted. For Example you could use a JobDataMap to store the maximum execution time on a per job instance basis.
Each Job could control its maximum execution time in a similar way.
To stop a job from the inside of the job itself the easiest way is to throw an exception after a specific amount of time. For example:
public class MyJob : IJob
{
Timer _t;
public MyJob()
{
TimeSpan maxRunningTime = TimeSpan.FromMinutes(1);
_t = new Timer(delegate { throw new JobExecutionException("took to long"); }, null, (int) maxRunningTime.TotalMilliseconds,
-1);
}
public void Execute(IJobExecutionContext context)
{
// do your word
// destroy T before leaving
_t = null;
}
}
Hope it helps :)
I have an asp.net website and want to do a task once a day.
the task is: sending email to users 2 days before expiration of their registration.
I used Quartz.NET version 1.0. I have wrote a sample code that opens a window in each second. Now I don't know where should I locate this code in my asp.net project?! it is now in a simple page. I want it to be independent from pages.
public class DumbJob : IJob
{
public DumbJob()
{
}
public void Execute(JobExecutionContext context)
{
Console.WriteLine("DumbJob is executing.");
System.Windows.Forms.MessageBox.Show("NICE");
}
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
// construct a scheduler factory
ISchedulerFactory schedFact = new StdSchedulerFactory();
// get a scheduler
IScheduler sched = schedFact.GetScheduler();
sched.Start();
// construct job info
JobDetail jobDetail = new JobDetail("myJob", null, typeof(DumbJob));
// fire every hour
Trigger trigger = TriggerUtils.MakeSecondlyTrigger();//.MakeHourlyTrigger();
// start on the next even hour
trigger.StartTimeUtc = TriggerUtils.GetEvenSecondDate(DateTime.UtcNow);
trigger.Name = "myTrigger";
sched.ScheduleJob(jobDetail, trigger);
}
}
There are various ways you can do that...but certainly it's probably better o build some sort of console applications for your case.
Frankly the simplest of which could be a windows schedule task that would trigger every day and launch an exe program (that you'd write using console dotnet) that would check soon-to-expire users and send an email when found...
If you don't want to have user + email code in various places (and centralize all this in your dotnet web app), then I'd create a SOAP/REST end point in your .NET webapp that would be called by a thin client, which would be scheduled by that "windows schedule task"
Quartz would give you more flexibility when it comes to scheduling and doing more enterprise things like job clustering / job high availability / job monitoring for example...
But that'd still be a .NET console app which would start a quartz scheduler, create a trigger, and run forever...(possibly wrapped into a windows "wrapper" service for more control)
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();
I've problem with running big number of concurrent Jobs in my Eclipse RCP application. When I start 100 Jobs (like the one bellow), they execute normally but after they are finished they are still visible in Progress View for about 10 seconds. I would like Progress View to clear Jobs immediately after they are finished. If I start less Jobs (eg. 10) Progress View refreshes it self immediately.
class MyJob extends Job
{
public MyJob(String name) {
super(name);
}
public IStatus run(IProgressMonitor monitor){
//SOME EXPENSIVE COMPUTATIONS
BigInteger bigint = new BigInteger("0");
for ( int i=0 ; i<100 ; i++ ) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
bigint = bigint.add(new BigInteger(Integer.toString(i)));
}
monitor.done();
System.out.println(new Random().nextInt());
return new Status(IStatus.OK, "foo", "OK");
}
}
each job is scheduled as a separate thread and in case there are lots of them locking/synchronization/thread management mechanisms take some overhead. for example some internal Eclipse Jobs code explicitly puts progress-bar-feedback mechanism into sleep for 250ms. such solutions probably pile up into long delays.
anyway having 100 entries in Progress View is not user firendly. I'd suggest grouping those jobs with Job.setProgressGroup(). perhaps having less entries in the view will cover up slow responsiveness.
In a case like this, I'd say it's better to allocate your own Threads than to use Jobs. Your 100 Jobs are going to start using the Job Threads that would be used to do Workbench maintenance. Allocating your own Threads means the Jobs Thread pool doesn't grow to the max value and stay there.
I'd have one Job that starts your Threads and reports progress to the Progress View. You could use SubMonitor to split the main IProgressMonitor into 100 so each of the Thread/Runnable pairs you start can report progress back to the main Job.