Java FX - How to terminate a ScheduledService - javafx

I wrote a little code to download some files from internet..if user click on cancel button this must be stopped..i use the cancel() method for do it..but it didn't work.
ScheduledService<Object> service = new ScheduledService<Object>() {
protected Task<Object> createTask() {
return new Task<Object>() {
protected Object call() {
if (checkinternet()) {
downloadFiles();
}
return null;
}
};
}
};
service.start();
In buttons action event handler i called cancel method for stop service..
but it wasn't successful..
service.cancel();
How do i do that...

There is no automatic way to cancel a task or service.
From the documentation (https://docs.oracle.com/javase/8/javafx/interoperability-tutorial/concurrency.htm):
Cancelling the Task.
There is no reliable way in Java to stop a thread in process. However, the task must stop processing whenever cancel is called on the task. The task is supposed to check periodically during its work whether it was cancelled by using the isCancelled method within the body of the call method.
The example referenced in the above block looks like this:
Task<Integer> task = new Task<Integer>() {
#Override protected Integer call() throws Exception {
int iterations;
for (iterations = 0; iterations < 100000; iterations++) {
if (isCancelled()) {
break;
}
System.out.println("Iteration " + iterations);
}
return iterations;
}
};
So you will have to implement the cancel logic by yourself, unfortunately.

Related

Flutter and external JAR Library: android.os.NetworkOnMainThreadException

Im trying to use olingo with Flutter on Android. I set up my channel and I can call the library but I keep getting this message:
E/AndroidRuntime(28391): FATAL EXCEPTION: main
E/AndroidRuntime(28391): Process: com.example.odata, PID: 28391
E/AndroidRuntime(28391): org.apache.olingo.client.api.http.HttpClientException: android.os.NetworkOnMainThreadException
E/AndroidRuntime(28391): at org.apache.olingo.client.core.communication.request.AbstractODataRequest.doExecute(AbstractODataRequest.java:312)
So it looks like it is running on the main thread - which is a no go as this would block. I tried the looper to ask Java to run on the UI Thread:
public void onMethodCall(MethodCall call, Result result) {
// Note: this method is invoked on the main thread.
Log.i("test", "using " + call.method);
String serviceUrl = "http://services.odata.org/OData/OData.svc/";
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
if (call.method.equals("getMetaData")) {
String metadata;
final Edm edm = ODataClientFactory.getClient().getRetrieveRequestFactory().getMetadataRequest(serviceUrl).execute().getBody();
metadata = edm.toString();
if (metadata != "") {
result.success(metadata);
} else {
result.error("UNAVAILABLE", "Metadata cannot read.", null);
}
} else {
result.notImplemented();
}
}
});
But Im still getting the same error.
So how exactly can I deal with external JAR Library which are doing blocking operations ? To my understanding an external call is a Future anyway so it will not block my Flutter thread anyway - but Android Java does not think so ...
This is my method call in flutter
Future<void> _getMetaData() async {
String metadata;
try {
final String result = await platform.invokeMethod('getMetaData');
metadata = result;
} on PlatformException catch (e) {
metadata = e.message;
}
setState(() {
_metadata = metadata;
});
}
Thanks for the answer, this is the solution for anyone that may be interested:
public void onMethodCall(MethodCall call, Result result) {
if (call.method.equals("getMetaData")) {
class MetadataLoader extends AsyncTask<String , Integer, String> {
#Override
protected String doInBackground(String... urls) {
// call your Java library method here, including blocking methods
return your_return_value;
}
protected void onPostExecute(String _result) {
// your_return_value is now passed in _result
result.success(_result);
}
}
new MetadataLoader().execute(); // Start the Async
}
On the flutter side,
Future<void> _getMetaData() async {
String metadata;
try {
final String result = await platform.invokeMethod('getMetaData');
// do something with the result
// the Flutter thread will stop at the await and resume when the Java
// will call result.success
}
}
You will need to create a new Java thread or Worker. (Note that the "main" thread and the "UI" thread are the same thing - so by posting to the main looper you've ended up in the same place - trying to do network i/o on the main thread.)
Yes, the Flutter engine is running in different threads, but you still need to leave the main native thread unblocked as it is responsible for detecting user input, etc.
Also note that when your blocking activity completes - on its non-main thread - it will likely want to deliver the response to Dart. To do this it will need to use part of your code above - to post the results back to the main thread, which can then invoke method channel operations.
You'll probably want to use your method channel bi-directionally. From flutter to native to request an operation (returning, say, a sequence number), and from native to flutter to deliver the results (quoting the sequence number so that the result can be tied back to the request).

gRPC services's Context CancellationListener is not fired when client cancels a service call

I have a streaming service that indefinitely streams from the server to a client until the client cancels.
On the server side, I have a thread that populates an ehcache with data sourced from a database.
Ehcache provides callbacks on cache events, i.e, when an item is added, when an item is removed, etc. I only care about notifying clients when an element is put into the cache, so when a client connects to my gRPC service, I register a notifyElementPut() callback with the cache, that has a reference to the connected clients StreamObserver:
public class GrpcAwareCacheEventListener extends CacheEventListenerAdapter {
private StreamObserver<FooUpdateResponse> responseObserver;
public GrpcAwareCacheEventListener(
StreamObserver<FooUpdateResponse> responseObserver) {
this.responseObserver = responseObserver;
}
#Override
public void notifyElementPut(Ehcache cache, Element element) throws CacheException {
Foo foo = (Foo) element.getObjectValue();
if (foo != null) {
responseObserver.onNext(
FooResponse.newBuilder().setFoo(foo).build());
}
}
}
My streaming foo service is as follows:
public void streamFooUpdates(Empty request,
StreamObserver<FooResponse> responseObserver) {
final CacheEventListener eventListener = new GrpcAwareCacheEventListener(responseObserver);
fooCache.getCacheEventNotificationService().registerListener(eventListener);
Context.current().withCancellation().addListener(new CancellationListener() {
public void cancelled(Context context) {
log.info("inside context cancelled callback");
fooCache.getCacheEventNotificationService().unregisterListener(eventListener);
}
}, ForkJoinPool.commonPool());
}
This all works fine, the client is notified of all foo updates as long as he is connected.
However, after the client disconnects or explicitly cancels the call, I expect that the server's Context's cancellation listener would fire, unregistering the callback with the cache.
This is not the case, regardless of whether the client shutdowns the channel, or explicitly cancels the call. (I expect the server side cancelled context to fire for both of these events). I'm wondering if my cancel semantics on the client side are incorrect, here is the my client code, taken from a test case:
Channel channel = ManagedChannelBuilder.forAddress("localhost", 25001)
.usePlaintext().build();
FooServiceGrpc.FooService stub = FooServiceGrpc
.newStub(channel);
ClientCallStreamObserver<FooResponse> cancellableObserver = new ClientCallStreamObserver<FooResponse>(){
public void onNext(FooResponse response) {
log.info("received foo: {}", response.getFoo());
}
public void onError(Throwable throwable) {
}
public void onCompleted() {
}
public boolean isReady() {
return false;
}
public void setOnReadyHandler(Runnable runnable) {
}
public void disableAutoInboundFlowControl() {
}
public void request(int i) {
}
public void setMessageCompression(boolean b) {
}
public void cancel(#Nullable String s, #Nullable Throwable throwable) {
}
};
stub.streamFooUpdates(Empty.newBuilder().build(), cancellableObserver);
Thread.sleep(10000); // sleep 10 seconds while messages are received.
cancellableObserver.cancel("cancelling from test", null); //explicit cancel
((ManagedChannel) chan).shutdown().awaitTermination(5, TimeUnit.SECONDS); //shutdown as well, for good measure.
Thread.sleep(7000); //channel should be shutdown by now.
}
I'm wondering why the server is not firing the "Context cancelled" callback.
Thanks!
You are not cancelling the client call correctly. The StreamObserver on the second argument of stub.streamFooUpdates() is your callback. You shouldn't call anything on that StreamObserver.
There are two ways to cancel the call from the client-side.
Option 1: Pass a ClientResponseObserver as the second argument, implement beforeStart(), which gives you a ClientCallStreamObserver, on which you can call cancel().
Option 2: Run stub.streamFooUpdates() inside a CancellableContext, and cancel the Context to cancel the call. Note that a CancellableContext must be always be cancelled, that's what the finally block is for.
CancellableContext withCancellation = Context.current().withCancellation();
try {
withCancellation.run(() -> {
stub.streamFooUpdates(...);
Thread.sleep(10000);
withCancellation.cancel(null);
});
} finally {
withCancellation.cancel(null);
}

Working with static method Asp.Net

Good night guys!
I'm having the following problem ...
I have a web application that runs a "thread" that takes messages from the queue (MSMQ) ... Everything works correctly .. the problem is when I get this message, I can not display .. because the method that returns the message content is a "static" ..
I need to perform a function in JS to display this message.
conclusion:
The method "ProcessMessage" can not be named because he is not a static method ...
My main goal is to call a function in JS passing as parameter (m.Body.ToString ()) which is the content of the message.
Can anyone help me?
Thank you for sharing your knowledge!
This is my code.
public void StartThread()
{
try
{
while (true)
{
PrepareQueue();
}
}
catch (Exception)
{ }
}
public static void PrepareQueue()
{
MessageQueue myQueue = new MessageQueue(".\\private$\\CTIQueue");
myQueue.Formatter = new XmlMessageFormatter(new Type[] { typeof(String) });
// Add an event handler for the ReceiveCompleted event.
myQueue.ReceiveCompleted += new ReceiveCompletedEventHandler(MyReceiveCompleted);
// Define wait handles for multiple operations.
WaitHandle[] waitHandleArray = new WaitHandle[10];
for (int i = 0; i < 10; i++)
{
// Begin asynchronous operations.
waitHandleArray[i] = myQueue.BeginReceive().AsyncWaitHandle;
}
// Specify to wait for all operations to return.
WaitHandle.WaitAll(waitHandleArray);
return;
}
private static void MyReceiveCompleted(Object source, ReceiveCompletedEventArgs asyncResult)
{
try
{
Thread.Sleep(2000);
MessageQueue mq = (MessageQueue)source;
// End the asynchronous receive operation.
System.Messaging.Message m = mq.EndReceive(asyncResult.AsyncResult);
ProcessMessage(m.Body.ToString()); <-- MY PROBLEM
}
catch (MessageQueueException)
{ }
return;
}
public void ProcessMessage(string message)
{
ScriptManager.RegisterStartupScript(this, GetType(), "popup", "NewCaller('" + message + "');", true);
}
Why not instantiate an object of the class and call ProcessMessage on it? Static methods can instantiate an object of the enclosing class and invoke instance methods on it.
private static void MyReceiveCompleted(Object source, ReceiveCompletedEventArgs asyncResult)
{
try
{
Thread.Sleep(2000);
MessageQueue mq = (MessageQueue)source;
// End the asynchronous receive operation.
System.Messaging.Message m = mq.EndReceive(asyncResult.AsyncResult);
new MyClass().ProcessMessage(m.Body.ToString()); <-- MY PROBLEM
}
catch (MessageQueueException)
{ }
return;
}
But if you are planning to invoke a client side code from server side, with reactive action happening at the server's end(which I think is your case) -- then I would prefer you use ASP.NET SignalR to signal the client that something interesting has happened at the server's end.

Configuring Quartz.Net to stop a job from executing, if it is taking longer than specified time span

I am working on making a scheduler, just like Windows Scheduler using Quartz.Net.
In Windows Scheduler, there is an option to stop a task from running if it takes more than the specified time. I have to implement the same in my scheduler.
But I am not able to find any extension method/setting to configure Trigger or Job accordingly.
I request some inputs or suggestions for it.
You can write small code to set a custom timout running on another thread. Implement IInterruptableJob interface and make a call to its Interrupt() method from that thread when the job should be interrupted. You can modify the following sample code as per your need. Please make necessary checks/config inputs wherever required.
public class MyCustomJob : IInterruptableJob
{
private Thread runner;
public void Execute(IJobExecutionContext context)
{
int timeOutInMinutes = 20; //Read this from some config or db.
TimeSpan timeout = TimeSpan.FromMinutes(timeOutInMinutes);
//Run your job here.
//As your job needs to be interrupted, let us create a new task for that.
var task = new Task(() =>
{
Thread.Sleep(timeout);
Interrupt();
});
task.Start();
runner = new Thread(PerformScheduledWork);
runner.Start();
}
private void PerformScheduledWork()
{
//Do what you wish to do in the schedled task.
}
public void Interrupt()
{
try
{
runner.Abort();
}
catch (Exception)
{
//log it!
}
finally
{
//do what you wish to do as a clean up task.
}
}
}

Workflow 4 CodeActivity not throwing TimeoutException

I am new to Windows Workflow and trying to write a Long Running process.
I am also trying to limit how long this process can run for.
I am calling WorkflowInvoker.Invoke to trigger my Workflow passing it a small timespan for testing.
If I try this certain activities, this seems to work perfectly.
But If I use a CodeActivity, it seems to ignore my timeout entirely.
Why is this? And how do I cause my CodeActivity to timeout if it takes too long?
An example working with a Delay Activity:
(In this example the TimeOutException is thrown)
Activity wf = new Sequence()
{
Activities =
{
new Delay()
{
Duration = TimeSpan.FromSeconds(10)
},
}
};
try
{
WorkflowInvoker.Invoke(wf, TimeSpan.FromSeconds(5));
}
catch (TimeoutException ex)
{
Console.WriteLine(ex.Message);
}
An example trying to use a CodeActivity:
(In this example the TimeOutException is not thrown)
public class LongActivity : CodeActivity
{
protected override void Execute(CodeActivityContext context)
{
Thread.Sleep(TimeSpan.FromSeconds(10));
}
}
Activity wf = new Sequence()
{
Activities =
{
new LongActivity()
}
};
try
{
WorkflowInvoker.Invoke(wf, TimeSpan.FromSeconds(5));
}
catch (TimeoutException ex)
{
Console.WriteLine(ex.Message);
}
The workflow runtime can only take action when it is in charge and if your activity takes 10 seconds to execute, or sleep, the runtime can't do anything about it. It won't schedule any new activities though because there is no remaining time left and would throw a TimeoutException instead.
Normally when you have long running work you would use an asynchronous activity, either an AsyncCodeActivity or a NativeActivity with a bookmark so the runtime is in control and can abort the workflow.

Resources