Pattern Name: DisableJobRequestsWhileRunningJob
Suppress redundant, time-consuming job requests. Prevent errors caused by lack of thread-safety in the job. Show the user that the job was accepted. Present an honest user interface.
A user can request a time-consuming operation, such as a printout, database update, file-system scan, or rocket launch. Often, the first steps of the operation provide no user feedback (the preparation to print is silent -- only later does the printer turn on and become noisy), so the user does not know if the request was accepted. Also, repeated requests (while the first request is being processed) may cause errors -- and even abort the first operation.
The user might accidentally double-click.
A bouncy switch may cause a single-click to be interpreted as a double-click.
The user might want to ensure a request is accepted by re-clicking.
The user interface indicates to the user what features are available.
Repeated requests are unnecessary, if the first request was accepted. It is unlikely that the user will intentionally request 2 print-outs by double-clicking, for example. (There may be another way to request 2 print-outs, or the user may be able to wait until the first job is finished before requesting another print-out.)
Repeated requests cause errors.
Wrap the job code with code that looks like:
1) Check the JobFeatureInUse flag.
If it is in use:
Should not reach here.
The "job" feature was accidentally called, or called from within code.
Typically, silently exit.
Other possibilities are to log an error,
raise an assert for debugging, or queue the request.
In any event, skip the remaining steps.
2) Set JobFeatureInUse = True
3) Use ObserverPattern for the flag (or call a MediatorPattern function)
that visibly disables all buttons that call the "job" feature.
4) Call the "job" feature.
5) Set JobFeatureInUse = False
6) Use ObserverPattern for the flag (or call a MediatorPattern function)
that visibly enables otherwise useful buttons that call the "job" feature.
The user knows that their request was accepted. This pattern does not tell the user whether the "job" feature hung, however. The user knows when their request finishes, but only if they are paying attention to when the button is reenabled. The user interface is more complicated.
Several such flags may interact in strange ways. At step 6, determining which buttons are "otherwise useful" and should be reenabled can be tricky.
In some programming environments, cancelling a job in the middle may prevent the button from being reenabled -- even if it is safe to use.