I have a JavaFX application which instantiates several Task objects.
Currently, my implementation (see below) calls the behavior runFactory() which performs computation under a Task object. Parallel to this, nextFunction() is invoked. Is there a way to have nextFunction() "wait" until the prior Task is complete?
I understand thread.join() waits until the running thread is complete, but with GUIs, there are additional layers of complexity due to the event dispatch thread.
As a matter of fact, adding thread.join() to the end of the code-segment below only ceases UI interaction.
If there are any suggestions how to make nextFunction wait until its prior function, runFactory is complete, I'd be very appreciative.
Thanks,
// High-level class to run the Knuth-Morris-Pratt algorithm.
public class AlignmentFactory {
public void perform() {
KnuthMorrisPrattFactory factory = new KnuthMorrisPrattFactory();
factory.runFactory(); // nextFunction invoked w/out runFactory finishing.
// Code to run once runFactory() is complete.
nextFunction() // also invokes a Task.
...
}
}
// Implementation of Knuth-Morris-Pratt given a list of words and a sub-string.
public class KnuthMorrisPratt {
public void runFactory() throws InterruptedException {
Thread thread = null;
Task<Void> task = new Task<Void>() {
#Override public Void call() throws InterruptedException {
for (InputSequence seq: getSequences) {
KnuthMorrisPratt kmp = new KnuthMorrisPratt(seq, substring);
kmp.align();
}
return null;
}
};
thread = new Thread(task);
thread.setDaemon(true);
thread.start();
}
When using Tasks you need to use setOnSucceeded and possibly setOnFailed to create a logic flow in your program, I propose that you also make runFactory() return the task rather than running it:
// Implementation of Knuth-Morris-Pratt given a list of words and a sub-string.
public class KnuthMorrisPratt {
public Task<Void> runFactory() throws InterruptedException {
return new Task<Void>() {
#Override public Void call() throws InterruptedException {
for (InputSequence seq: getSequences) {
KnuthMorrisPratt kmp = new KnuthMorrisPratt(seq, substring);
kmp.align();
}
return null;
}
};
}
// High-level class to run the Knuth-Morris-Pratt algorithm.
public class AlignmentFactory {
public void perform() {
KnuthMorrisPrattFactory factory = new KnuthMorrisPrattFactory();
Task<Void> runFactoryTask = factory.runFactory();
runFactoryTask.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
#Override
public void handle(WorkerStateEvent t)
{
// Code to run once runFactory() is completed **successfully**
nextFunction() // also invokes a Task.
}
});
runFactoryTask.setOnFailed(new EventHandler<WorkerStateEvent>() {
#Override
public void handle(WorkerStateEvent t)
{
// Code to run once runFactory() **fails**
}
});
new Thread(runFactoryTask).start();
}
}
Related
Im trying to perform a synchronization task without blocking UI thread. I have implemented a Android Service to do so, but I found out, if the synchronization task needs too much computational time, the UI thread was blocked. So I tried the migration to IntentService. This is how my IntentService looks like:
[Service]
public class SynchronizeIntentService : IntentService
{
static readonly string TAG = typeof(SynchronizeIntentService).FullName;
private NotificationCompat.Builder Builder;
private NotificationManagerCompat NotificationManager;
public SynchronizeIntentService() : base("SynchronizeIntentService")
{
}
public override void OnDestroy()
{
var tmp = 5;
base.OnDestroy();
}
private NotificationChannel createNotificationChannel()
{
var channelId = Constants.NOTIFICATION_CHANNELID;
var channelName = "My Notification Service";
var Channel = new NotificationChannel(channelId, channelName, Android.App.NotificationImportance.Default);
Channel.LightColor = Android.Resource.Color.HoloBlueBright;
Channel.LockscreenVisibility = NotificationVisibility.Public;
return Channel;
}
private void createForegroundService()
{
var mNotificationManager = GetSystemService(Context.NotificationService) as NotificationManager;
if (Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O)
{
mNotificationManager.CreateNotificationChannel(createNotificationChannel());
}
var notificationBuilder = new NotificationCompat.Builder(this, Constants.NOTIFICATION_CHANNELID);
GenerateNotification();
StartForeground(Constants.SERVICE_RUNNING_NOTIFICATION_ID, Builder.Notification);
}
private void GenerateNotification()
{
NotificationManager = NotificationManagerCompat.From(this);
Builder = new NotificationCompat.Builder(this, Constants.NOTIFICATION_CHANNELID);
Builder.SetContentTitle(ContaScan.Classes.Localize.GetString("Global_SynchProcess", ""))
.SetSmallIcon(Resource.Drawable.icon)
.SetPriority(NotificationCompat.PriorityLow);
}
protected async override void OnHandleIntent(Intent intent)
{
Log.Debug(TAG, "Service Started!");
await Synch();
Log.Debug(TAG, "Service Stopping!");
StopForeground(true);
this.StopSelf();
}
public override StartCommandResult OnStartCommand(Intent intent, [GeneratedEnum] StartCommandFlags flags, int startId)
{
base.OnStartCommand(intent, flags, startId);
createForegroundService();
return StartCommandResult.Sticky;
}
private async Task Synch()
{
//Large synch process
}
}
And this is how the service is getting started:
startServiceIntent = new Intent(Android.App.Application.Context, typeof(SynchronizeIntentService));
startServiceIntent.SetAction(Constants.ACTION_START_SERVICE);
ContextWrapper contextWrapper = new ContextWrapper(Android.App.Application.Context);
contextWrapper.StartService(startServiceIntent);
The problem is OnDestroy() method is called while the Synch() task is being performed and looks like the IntentService is being killed before ending the process.
What am I doing wrong?
First, check your API level. This class was deprecated in API level 30.
And then, when you use the OnHandleIntent, do not call Service.stopSelf().
This method is invoked on the worker thread with a request to process. Only one Intent is processed at a time, but the processing happens on a worker thread that runs independently from other application logic. So, if this code takes a long time, it will hold up other requests to the same IntentService, but it will not hold up anything else. When all requests have been handled, the IntentService stops itself, so you should not call Service.stopSelf().
For more details, please check the link below. https://developer.android.com/reference/android/app/IntentService#onHandleIntent(android.content.Intent)
I was trying reactor library and I'm not able to figure out why below mono never return back with onNext or onComplete call. I think I missing very trivial thing. Here's a sample code.
MyServiceService service = new MyServiceService();
service.save("id")
.map(myUserMono -> new MyUser(myUserMono.getName().toUpperCase(), myUserMono.getId().toUpperCase()))
.subscribe(new Subscriber<MyUser>() {
#Override
public void onSubscribe(Subscription s) {
System.out.println("Subscribed!" + Thread.currentThread().getName());
}
#Override
public void onNext(MyUser myUser) {
System.out.println("OnNext on thread " + Thread.currentThread().getName());
}
#Override
public void onError(Throwable t) {
System.out.println("onError!" + Thread.currentThread().getName());
}
#Override
public void onComplete() {
System.out.println("onCompleted!" + Thread.currentThread().getName());
}
});
}
private static class MyServiceService {
private Repository myRepo = new Repository();
public Mono<MyUser> save(String userId) {
return myRepo.save(userId);
}
}
private static class Repository {
public Mono<MyUser> save(String userId) {
return Mono.create(myUserMonoSink -> {
Future<MyUser> submit = exe.submit(() -> this.blockingMethod(userId));
ListenableFuture<MyUser> myUserListenableFuture = JdkFutureAdapters.listenInPoolThread(submit);
Futures.addCallback(myUserListenableFuture, new FutureCallback<MyUser>() {
#Override
public void onSuccess(MyUser result) {
myUserMonoSink.success(result);
}
#Override
public void onFailure(Throwable t) {
myUserMonoSink.error(t);
}
});
});
}
private MyUser blockingMethod(String userId) throws InterruptedException {
Thread.sleep(5000);
return new MyUser("blocking", userId);
}
}
Above code only prints Subcribed!main. What I'm not able to figure out is why that future callback is not pushing values through myUserMonoSink.success
The important thing to keep in mind is that a Flux or Mono is asynchronous, most of the time.
Once you subscribe, the asynchronous processing of saving the user starts in the executor, but execution continues in your main code after .subscribe(...).
So the main thread exits, terminating your test before anything was pushed to the Mono.
[sidebar]: when is it ever synchronous?
When the source of data is a Flux/Mono synchronous factory method. BUT with the added pre-requisite that the rest of the chain of operators doesn't switch execution context. That could happen either explicitly (you use a publishOn or subscribeOn operator) or implicitly (some operators like time-related ones, eg. delayElements, run on a separate Scheduler).
Simply put, your source is ran in the ExecutorService thread of exe, so the Mono is indeed asynchronous. Your snippet on the other hand is ran on main.
How to fix the issue
To observe the correct behavior of Mono in an experiment (as opposed to fully async code in production), several possibilities are available:
keep subscribe with system.out.printlns, but add a new CountDownLatch(1) that is .countDown() inside onComplete and onError. await on the countdown latch after the subscribe.
use .log().block() instead of .subscribe(...). You lose the customization of what to do on each event, but log() will print those out for you (provided you have a logging framework configured). block() will revert to blocking mode and do pretty much what I suggested with the CountDownLatch above. It returns the value once available or throws an Exception in case of error.
instead of log() you can customize logging or other side effects using .doOnXXX(...) methods (there's one for pretty much every type of event + combinations of events, eg. doOnSubscribe, doOnNext...)
If you're doing a unit test, use StepVerifier from the reactor-tests project. It will subscribe to the flux/mono and wait for events when you call .verify(). See the reference guide chapter on testing (and the rest of the reference guide in general).
Issue is that in created anonymous class onSubscribe method does nothing.
If you look at implementation of LambdaSubscriber, it requests some number of events.
Also it's easier to extend BaseSubscriber as it has some predefined logic.
So your subscriber implementation would be:
MyServiceService service = new MyServiceService();
service.save("id")
.map(myUserMono -> new MyUser(myUserMono.getName().toUpperCase(), myUserMono.getId().toUpperCase()))
.subscribe(new BaseSubscriber<MyUser>() {
#Override
protected void hookOnSubscribe(Subscription subscription) {
System.out.println("Subscribed!" + Thread.currentThread().getName());
request(1); // or requestUnbounded();
}
#Override
protected void hookOnNext(MyUser myUser) {
System.out.println("OnNext on thread " + Thread.currentThread().getName());
// request(1); // if wasn't called requestUnbounded() 2
}
#Override
protected void hookOnComplete() {
System.out.println("onCompleted!" + Thread.currentThread().getName());
}
#Override
protected void hookOnError(Throwable throwable) {
System.out.println("onError!" + Thread.currentThread().getName());
}
});
Maybe it's not the best implementation, I'm new to reactor too.
Simon's answer has pretty good explanation about testing asynchronous code.
I am building a download manager in javafx
I have added function to download button which initialises new task.More than one download is also being executed properly.
But I need to add pause and resume function. Please tell how to implement it using executor. Through execute function of Executors, task is being started but how do i pause & then resume it??
Below I am showing relevant portions of my code. Please tell if you need more details. thanks.
Main class
public class Controller implements Initializable {
public Button addDownloadButton;
public Button pauseResumeButton;
public TextField urlTextBox;
public TableView<DownloadEntry> downloadsTable;
ExecutorService executor;
#Override
public void initialize(URL location, ResourceBundle resources) {
// here tableview and table columns are initialised and cellValueFactory is set
executor = Executors.newFixedThreadPool(4);
}
public void addDownloadButtonClicked() {
DownloadEntry task = new DownloadEntry(new URL(urlTextBox.getText()));
downloadsTable.getItems().add(task);
executor.execute(task);
}
public void pauseResumeButtonClicked() {
//CODE FOR PAUSE AND RESUME
}
}
DownloadEntry.java
public class DownloadEntry extends Task<Void> {
public URL url;
public int downloaded;
final int MAX_BUFFER_SIZE=50*1024;
private String status;
//Constructor
public DownloadEntry(URL ur) throws Exception{
url = ur;
//other variables are initialised here
this.updateMessage("Downloading");
}
#Override
protected Void call() {
file = new RandomAccessFile(filename, "rw");
file.seek(downloaded);
stream = con.getInputStream();
while (status.equals("Downloading")) {
byte buffer=new byte[MAX_BUFFER_SIZE];
int c=stream.read(buffer);
if (c==-1){
break;
}
file.write(buffer,0,c);
downloaded += c;
status = "Downloading";
}
if (status.equals("Downloading")) {
status = "Complete";
updateMessage("Complete");
}
return null;
}
}
You may be interested in Concurrency in JavaFX.
I guess you should also have a look at pattern Observer.
By the way I think you should not use constant string as a status ("Downloading", etc), creating an enum would be a better approach.
In your loop, around the read/write part, there should be a synchronization mechanism, controlled by your pause/resume buttons (see the two links).
I have an external dll written in C# and I studied from the assemblies documentation that it writes its debug messages to the Console using Console.WriteLine.
this DLL writes to console during my interaction with the UI of the Application, so i don't make DLL calls directly, but i would capture all console output , so i think i got to intialize in form load , then get that captured text later.
I would like to redirect all the output to a string variable.
I tried Console.SetOut, but its use to redirect to string is not easy.
As it seems like you want to catch the Console output in realtime, I figured out that you might create your own TextWriter implementation that fires an event whenever a Write or WriteLine happens on the Console.
The writer looks like this:
public class ConsoleWriterEventArgs : EventArgs
{
public string Value { get; private set; }
public ConsoleWriterEventArgs(string value)
{
Value = value;
}
}
public class ConsoleWriter : TextWriter
{
public override Encoding Encoding { get { return Encoding.UTF8; } }
public override void Write(string value)
{
if (WriteEvent != null) WriteEvent(this, new ConsoleWriterEventArgs(value));
base.Write(value);
}
public override void WriteLine(string value)
{
if (WriteLineEvent != null) WriteLineEvent(this, new ConsoleWriterEventArgs(value));
base.WriteLine(value);
}
public event EventHandler<ConsoleWriterEventArgs> WriteEvent;
public event EventHandler<ConsoleWriterEventArgs> WriteLineEvent;
}
If it's a WinForm app, you can setup the writer and consume its events in the Program.cs like this:
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
using (var consoleWriter = new ConsoleWriter())
{
consoleWriter.WriteEvent += consoleWriter_WriteEvent;
consoleWriter.WriteLineEvent += consoleWriter_WriteLineEvent;
Console.SetOut(consoleWriter);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
static void consoleWriter_WriteLineEvent(object sender, Program.ConsoleWriterEventArgs e)
{
MessageBox.Show(e.Value, "WriteLine");
}
static void consoleWriter_WriteEvent(object sender, Program.ConsoleWriterEventArgs e)
{
MessageBox.Show(e.Value, "Write");
}
It basically amounts to the following:
var originalConsoleOut = Console.Out; // preserve the original stream
using(var writer = new StringWriter())
{
Console.SetOut(writer);
Console.WriteLine("some stuff"); // or make your DLL calls :)
writer.Flush(); // when you're done, make sure everything is written out
var myString = writer.GetStringBuilder().ToString();
}
Console.SetOut(originalConsoleOut); // restore Console.Out
So in your case you'd set this up before making calls to your third-party DLL.
You can also call SetOut with Console.OpenStandardOutput, this will restore the original output stream:
Console.SetOut(new StreamWriter(Console.OpenStandardOutput()));
Or you can wrap it up in a helper method that takes some code as an argument run it and returns the string that was printed. Notice how we gracefully handle exceptions.
public string RunCodeReturnConsoleOut(Action code)
{
string result;
var originalConsoleOut = Console.Out;
try
{
using (var writer = new StringWriter())
{
Console.SetOut(writer);
code();
writer.Flush();
result = writer.GetStringBuilder().ToString();
}
return result;
}
finally
{
Console.SetOut(originalConsoleOut);
}
}
Using solutions proposed by #Adam Lear and #Carlo V. Dango I created a helper class:
public sealed class RedirectConsole : IDisposable
{
private readonly Action<string> logFunction;
private readonly TextWriter oldOut = Console.Out;
private readonly StringWriter sw = new StringWriter();
public RedirectConsole(Action<string> logFunction)
{
this.logFunction = logFunction;
Console.SetOut(sw);
}
public void Dispose()
{
Console.SetOut(oldOut);
sw.Flush();
logFunction(sw.ToString());
sw.Dispose();
}
}
which can be used in the following way:
public static void MyWrite(string str)
{
// print console output to Log/Socket/File
}
public static void Main()
{
using(var r = new RedirectConsole(MyWrite)) {
Console.WriteLine("Message 1");
Console.WriteLine("Message 2");
}
// After the using section is finished,
// MyWrite will be called once with a string containing all messages,
// which has been written during the using section,
// separated by new line characters
}
I created app which user can start from menu and from icon. I do not use GlobalEventListener in my app, just register ApplicationMenuitem. And now I am getting error: previous instance still active when launch my app.
Steps to reproduce not so trivial:
launch app from icon
do not close it, just switch to another app
launch app from icon again
I founded article in blackberry's forum about it , but I can't find solution where I should remove my ApplicationMenuItem: it added on phone boot and should show all the time.
My code:
public class Jingu extends UiApplication {
public static void main(String[] args) {
ApplicationManager app = ApplicationManager.getApplicationManager();
boolean keepGoing = true;
while (keepGoing) {
if (app.inStartup()) {
try {
Thread.sleep(1000);
} catch (Exception e) {}
} else {
keepGoing = false;
}
}
Jingu theApp = new Jingu();
theApp.initMenuItem();
theApp.showMainScreen();
theApp.enterEventDispatcher();
}
public Jingu() {
}
public void showMainScreen() {
showScreen(new JinguMainScreen(this));
}
public void initMenuItem() {
// Create menu item
Object o = RuntimeStore.getRuntimeStore().get(JinguMenuItem.MY_MENU_ID);
// register only if not done already.
if (o == null) {
new JinguMenuItem(this).registerInstance();
}
}
public void showScreen(Screen aScreen) {
synchronized (Application.getEventLock()) {
try {
UiApplication.getUiApplication().popScreen(aScreen);
} catch (Exception e) {
}
UiApplication.getUiApplication().pushScreen(aScreen);
}
}
}
public class JinguMenuItem extends ApplicationMenuItem {
public static final long MY_MENU_ID = 0xb9739d5240d5943dL;
private final Jingu jingu;
public JinguMenuItem(Jingu jingu) {
super(0x350100);
this.jingu = jingu;
}
public void registerInstance() {
Object menuItem = RuntimeStore.getRuntimeStore().remove(MY_MENU_ID);
if (menuItem == null) {
ApplicationMenuItemRepository amir = ApplicationMenuItemRepository.getInstance();
amir.addMenuItem(ApplicationMenuItemRepository.MENUITEM_SYSTEM, this);
RuntimeStore.getRuntimeStore().put(MY_MENU_ID, this);
}
}
public Object run(Object context) {
jingu.setDefaultFont(Font.getDefault());
jingu.setMainApp(false);
jingu.setBbmEditField(null);
jingu.showMainScreen();
return context;
}
public String toString() {
return "My Menu";
}
}
plz advice where I should delete ApplicationMenuItem in my app?
my regards,
Vadim
If you are registering an ApplicationMenuItem from your application, as a user I would consider it bad style for your application to remove and exit, even if RIM provided a way to do this. You may want to separate your application into two parts. One provides the minimal support for responding to the ApplicationMenuItem selection, that starts automatically and runs in the background. The other has all the rest and can run and exit as needed.
My solution for this situation is:
create alternative entry point and run it on app load
register menu in it
do not use runtimeStore