I developed a JavaFX application using MVC and DAO patterns. From the user interface the user can press a button to start export from MS Access to SQLite. This may take a long time, so I created a task (in the Controller). The task invokes a method of the Model "exportFromAccessToSQLite". All the logic of the database is in the Model. It all works fine. But I'd like to add a button in the user interface which when pressed stops the current operation. I would like to enter the code in the controller. How can I do?
The code is this:
Model objModel = new Model();
Task worker = new Task() {
#Override
protected Void call() throws Exception {
objModel.exportFromAccessToSQLite(fileAccess, directoryDest);
updateProgress(1, 1);
return null;
}
};
prgEspIndicator.progressProperty().bind(worker.progressProperty());
new Thread(worker).start();
Related
I am doing a windows service (call it SampleService), every is fine. When I started then stopped service through Windows Service Management Tool (service.msc), it run properly.
But my service will be request Start and Stop by another application. So I will not use Windows Service Management Tool in this case.
This is my service implement.
using System.ServiceProcess;
public partial class SampleService : ServiceBase
{
public SampleService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
this.WriteLog("OnStart");
// Doing start service logic down here
// Some service logic like create some files.
// Or just leave it empty like a brand new Windows Service.
}
protected override void OnStop()
{
this.WriteLog("OnStop");
// Doing clean service logic down here.
// Some service logic like: delete files.
// Or just leave it empty like a brand new Windows Service.
}
static readonly object synObject = new object();
public void WriteLog(string message)
{
if (string.IsNullOrEmpty(message))
{
return;
}
// Write log.
lock (synObject)
{
using (var wr = new StreamWriter(#"C:\logfile.txt", true))
{
wr.WriteLine(DateTime.Now + "-" + message);
}
}
}
}
And this is code logic use to Start and Stop service inside my another application. I can not modify this another application. The bellow source code simulate what happen.
class Program
{
static void Main(string[] args)
{
ServiceController sc = new ServiceController("SampleService");
// start service
sc.Start();
// doing some logic cost deltaTime or just stand by in deltaTime.
Thread.Sleep(deltaTime);
try
{
// stop service first time, nothing happen.
sc.Stop();
}
catch
{
}
try
{
// stop service second times, by dump people or apllication.
sc.Stop();
}
catch
{
// It got an exception here: "The service cannot accept control messages at this time".
// But the service did stopped.
}
}
}
The problem is:"When deltaTime is too short (bellow 3000ms with empty OnStart(), OnStop()), Service will stop incorrectly. The output log OnStop will never show up, that mean OnStop method did not called.
My service will doing clean up work in OnStop (like delete some file), but if it not be called, these files still there.
I cannot change logic of another application but I can change SampleService.
I want to ask:
Is this an Windows Service base issue and I cant do anything with it?
What ever it is, can I do clean up some where else?
Thank you!
I have a MVC.Net4 Application in which i have Longrunning backround operations which is why i use the System.Threading.Tasks.Task Class.
I start the Tasks after the User clicked a certain Button on the GUI, from that Task im going to use async methods from a intern API which i need to await. This is all working.
public ActionResult DoAsyncAction()
{
//ReturnValue that needs to be further populated by the async action in productive environment
var arv = new AsyncReturnValue
{
ProgressBar = new ProgressBar {Action = "SomeAction", User = "SomeUser"}
};
var t = new Task<AsyncReturnValue>(DoAction, arv);
//Add a Progressbar before Task starts so i can visualize the process on the view
HttpContext.GetSession().ProgressBars.Add(arv.ProgressBar);
//from my understanding this is similar to an event that gets triggered when my DoAction Method finished so i need to remove
//the progressbar there again since the process will be finished in that case
t.ContinueWith(DoActionkComplete);
t.Start();
//Returns the User to the Index Page while the Task is processing
return View("Index");
}
Now what i really want to do is visualizing the operation. I use jQuery Progressbars on the GUI and my Own ProgressBar Object in the Session for this. I have a List of ProgressBars on my Session and a PartialView strongly Typed to a List of those ProgressBars.
ProgressBar Class:
public class ProgressBar
{
public string Action { get; set; }
public string User { get; set; }
}
PartialView:
#using AsyncProj.Models
#model List<AsyncProj.Models.ProgressBar>
#{
ViewBag.Title = "ProgressPartial";
}
#{
var foo = (MySessionObject) HttpContext.Current.Session["__MySessionObject"];
foreach (var pb in foo.ProgressBars)
{
<div style="border: 1px solid black">
<p>#pb.Action</p>
<div id="progressbar">This will be turned into a ProgressBar via jQuery.</div >
</div>
}
}
And then the Object i have in my Session:
public class MySessionObject
{
public List<ProgressBar> ProgressBars { get; set; }
public string User { get; set; }}
Whenever i start a new Task i will add another ProgressBar to that List, which works just fine.
No where i get into Troubles is when i want to Remove the ProgressBars from Session again.
In the DoActionkComplete Method which i set in Task.ContinueWith() i want to Remove the ProgressBar corresponding to the finished action. I have the ProgressBar Ready there, its stored in my AsyncReturnValue Class which i have in the Task.Result at this point:
public class AsyncReturnValue
{
public ProgressBar ProgressBar { get; set; }
}
In this Method i would like to remove the Progressbar from the Session with
HttpContext.GetSession().ProgressBars.Remove(pbToRemove). But the problem with that im still operating on a different Thread so i have no valid HttpContext there and my SessionObject is null on that Thread.
This is what my DoActionComplete Method looks right now:
public void DoActionkComplete(Task<AsyncReturnValue> t)
{
//i set the user hardcode because its only a demo
DeleteProgress.Add(new ProgressBarDeleteObject {ProgressBar = t.Result.ProgressBar, User = "Asd123"});
}
I created a Workaround where i have a static List of Progressbars on my Controller. In the DoActionComplete Method i add the ProgressBars i want to delete to that List. I need to use polling (with jQuery $.get() and setinterval) in order to delete them.
I have a custom Class for the DeleteList on which i can set a Username so i know who is the Owner of that ProgressBar and only show it to him, else everyone would see it because its Static.
public class ProgressBarDeleteObject
{
public ProgressBar ProgressBar { get; set; }
public string User { get; set; }
}
Dont get me wrong, my workaround works just fine but i want to know the clean way. From what i know static Lists on Controllers could technically grow very big and slow the site down. Such Lists also lose its entries when the ApplicationPool restarts the Application.
So my Actual Question would be how can i access a HttpContext SessionObject from a different Thread like i'm using? And if its not possible, what would be the proper Way to achieve what i want?
So my Actual Question would be how can i access a HttpContext SessionObject from a different Thread like i'm using?
That's not possible.
And if its not possible, what would be the proper Way to achieve what i want?
First, let's back up to the original scenario. The problem is here:
I have a MVC.Net4 Application in which i have Longrunning backround operations which is why i use the System.Threading.Tasks.Task Class.
That's the wrong solution for that scenario. The proper solution is to have a reliable queue (Azure queue / MSMQ) with an independent background process (Azure webjob / Win32 service) doing the processing. This is a more reliable solution because any work you toss onto the ASP.NET thread pool may be lost (especially if you don't inform ASP.NET about that work).
Once you have this architecture set up, then you can use SignalR to communicate from your web server to your clients. SignalR will use polling if it has to, but it can also use more efficient methods (such as websockets).
You can specify the SynchroniztionContext that the ContinueWith task continues on and then you should be able to access the progress bars. Try changing your t.ContinueWith(DoActionkComplete); call to
t.ContinueWith(DoActionkComplete, TaskScheduler.FromCurrentSynchronizationContext());
If you are using .NET 4.5 you can rewrite your method with async\await
public async Task<ActionResult> DoAsyncAction()
{
//ReturnValue that needs to be further populated by the async action in productive environment
var arv = new AsyncReturnValue
{
ProgressBar = new ProgressBar {Action = "SomeAction", User = "SomeUser"}
};
//Add a Progressbar before Task starts so i can visualize the process on the view
HttpContext.GetSession().ProgressBars.Add(arv.ProgressBar);
var result = await Task.Run(DoAction());
//i set the user hardcode because its only a demo
DeleteProgress.Add(new ProgressBarDeleteObject {ProgressBar = result.ProgressBar, User = "Asd123"});
//Returns the User to the Index Page while the Task is processing
return View("Index");
}
And if you make the DoAction method async as well, you can remove the Task.Run part as that uses up a thread from the thread pool.
I am developing a wizard using eclipse plugin development.
Requirement:
I have to create a context menu that needs to get populated as soon as the user right clicks on the source folder in java project. once the User performs the first step my handler needs to get the selected src folder in my wizard. My wizard contains a treeviewer where i need to get the selected src folder packaged.
My analysis:
i have my handler class that gets the selected packages
SampleHandler.java
public Object execute(ExecutionEvent event) throws ExecutionException {
shell = HandlerUtil.getActiveShell(event);
// Initializing workbench window object
IWorkbenchWindow window = (IWorkbenchWindow) HandlerUtil.getActiveWorkbenchWindow(event);
ISelection sel = HandlerUtil.getActiveMenuSelection(event);
final IStructuredSelection selection = (IStructuredSelection) sel;
Object firstElement = selection.getFirstElement();
if (firstElement instanceof IPackageFragment) {
// Get the selected fragment
IPackageFragment packageFragment = (IPackageFragment) firstElement;
modelPackage = packageFragment.getElementName();
boolean a =!ProjectResourceHelper.isEntityBasePackage(modelPackage);
if(a == true){
MessageDialog.openInformation(shell, "Warning", "Please click from entity base package");
Shell shell = HandlerUtil.getActiveShell(event);
GreenWizard wizard = new GreenWizard();
WizardDialog dialog = new WizardDialog( part.getSite().getShell(), wizard);
dialog.create();
dialog.open();
return null;
}
try{
window.run(true, true, new IRunnableWithProgress(){
#Override
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
monitor.beginTask("Layer codes are being generated...", 1);
// Invocation of generate layers method
monitor.worked(1);
// Done with operation completion.
monitor.done();
}
});
}
catch(InvocationTargetException ite){
MessageDialog.openError(shell, "Greenfield Code Generation Exception", ite.getMessage());
}
catch (InterruptedException ie) {
MessageDialog.openError(shell, "Greenfield Code Generation Exception", ie.getMessage());
}
}
I have my main wizard class that is called within this method.
GreenWizard wizard = new GreenWizard();
and my main wizard in return calls my wizard page where i need to get the selection performed on right click by the user.
My Wizardpageclass
public GenerateGreenfieldLayer(IWorkbench workbench,
IStructuredSelection selection) {
super("Greenfield");
setImageDescriptor(ResourceManager
.getImageDescriptor("\\icons\\greenfield-new-wiz.png"));
setTitle("GreenField Generate layer");
setDescription("Select specfic class to grenerate Layers");
}
/**
* Create contents of the wizard.
*
* #param parent
*/
#Override
public void createControl(Composite parent) {
Composite container = new Composite(parent, SWT.NULL);
setControl(container);
container.setLayout(new GridLayout(2, false));
final CheckboxTreeViewer treeViewer = new CheckboxTreeViewer(container,
SWT.BORDER);
tree = treeViewer.getTree();
tree.setToolTipText("Choose package");
GridData gd_tree = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1);
gd_tree.widthHint = 280;
gd_tree.heightHint = 140;
tree.setLayoutData(gd_tree);
treeViewer.setContentProvider(new GreenfieldTreeContentProvider());
treeViewer.setLabelProvider(new WorkbenchLabelProvider());
treeViewer.addSelectionChangedListener(new ISelectionChangedListener () {
public void selectionChanged(SelectionChangedEvent event) {
}
});
}
Can anyone please guide me how to get the selection from object method and pass as treeviewer initial input in my wizard page.
Please correct me if i am missing any steps as i am very new to this.
Thanks in advance
You should separate the code into the following pieces and dataflows:
Handler: get the selection and create the wizard and wizard dialog (as you do already)
Handler->Wizard: use the Wizard's constructor or a custom init(foo) method (which you call from the handler) to set the selected object (or whatever you want to pass as initial data) from the handler
Wizard->WizardPage: When creating the Wizard, instantiate the WizardPage(s) and pass the selection to the wizard pages. (If you need a more complex model which is shared between the Wizard and its pages consider creating an instantiating a simple value-holder class as your wizard model; i.e., a simple java class with your data and getters/setters. That object can then be shared across the pages if you pass it to every page's constructor)
WizardPage: create UI for wizard page, let user modify the model
WizardPage->Wizard: if you do not use the shared wizard model via a value-holder class, have a getXxx() method to let the wizard access the user's input from the page
Wizard: implement Wizard.performFinish() to do the work at the end of the wizard using getContainer().run() instead of having the window.run() call in your handler.
I want to unit test the custom controls I create for a windows store project. Just simple things like "there is a button when X is true".
However, I can't seem to even instantiate the controls in a testing context. Whenever I try to invoke the constructor, I get an exception related to not being run in the UI context. I've also been unable to create coded UI test projects that target windows store projects.
How do I programmatically instantiate a control to test? How do I create a WinRT UI synchronization context?
How do I programmatically send "user" command events to a control?
How do I programmatically instantiate/teardown the entire application?
I've found a hacky way to make non-interactive parts work: with the function Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync.
Obvious, right? However, this still leaves open the question of how to emulate user actions.
/// Runs an action on the UI thread, and blocks on the result
private static void Ui(Action action) {
Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(
CoreDispatcherPriority.Normal,
() => action()
).AsTask().Wait();
}
/// Evaluates a function on the UI thread, and blocks on the result
private static T Ui<T>(Func<T> action) {
var result = default(T);
Ui(() => { result = action(); });
return result;
}
[TestMethod]
public void SliderTest() {
// constructing a Slider control is only allowed on the UI thread, so wrap it in UI
var slider = Ui(() => new Slider());
var expected = 0;
// accessing control properties is only allowed on the UI thread, so same deal
Assert.AreEqual(expected, Ui(() => slider.Value));
}
I have searched the web for the correct answer, but I've been failing to achieve this :
In EntryPoint class, I need to manage widgets according to events that occur in nested widgets. I've cleaned of the code to focus only on what is important here.
I have built a few UiBinder widgets, for example, a Login pane where the user can enter his credentials. In my EntryPoint class, I add the widgets in the correct position.
// This is from EntryPoint class
public void onModuleLoad() {
LoginPane lp = new LoginPane();
RootPanel.get("headerRightPane").add(lp);
lp.setFocus();
// Other widgets added in same manner after this point...
}
I would like a successful login to remove the LoginPane and replace it by another widget (AccountPane) that would show the account information for the user that is logged in. I have an onClick event, in LoginPane, that sends a request to a fully functional Servlet that checks the credentials. At this exact point, if the Servlet determines that the login is indeed successful, I would like to fire a "successfulLogin" event (from LoginPane) that could notify the EntryPoint class that the LoginPane can now be replaced by the AccountPane.
// This is from LoginPane class
#UiHandler("loginButton")
void onClick(ClickEvent e) {
checkCredentials(usernameField.getText(), passwordField.getText());
}
public void checkCredentials(String username, String password) {
String usernameToServer = username;
String passwordToServer = password;
credentialsService.credentialsServer(usernameToServer, passwordToServer,
new AsyncCallback<CredentialsPaneContent>() {
public void onFailure(Throwable caught) {
answerLabel.setText(Utilities.SERVER_ERROR);
}
public void onSuccess(CredentialsPaneContent result) {
if ( result == null ) {
answerLabel.setText("Login Failed.");
} else {
// Fire event here (to be caught by EntryPoint class)
answerLabel.setText("Login Successful.");
}
}
});
}
So, the question : How should I proceed to create, fire and listen to the event from my nested widget?
Use an EventBus. Additionally, consider adopting the Model-View-Presenter pattern to keep your application maintainable as it grows:
Large scale application development and MVP, Part I
Large scale application development and MVP, Part II
GWT MVP Development with Activities and Places
Lets have an interface which is implemented by EntryPoint class,
now have a referrence of interface type which actually an object of interface.
Using this interface referrence invoke the listner(interface) mothod, which serves your purpose.