Is code run from Platform.runLater thread safe? - javafx

If I have code ran entirely from within Platform.runLater, is that code automatically thread safe?
My understanding is that code ran on Platform.runLater is ran on the JavaFX application thread, which there is only one.
For example if I manipulate an hash map entirely in Plaform.runLater, I don't have to worry about multiple threads, right?

Whether or not using Platform#runLater(Runnable) is thread-safe is entirely dependent on how you use it. The example you give is you have a Map visible from a background thread but only ever manipulate it on the JavaFX Application Thread via runLater. Maybe something like:
// executing on background thread
Object newKey = ...;
Object newVal = ...;
Platform.runLater(() -> map.put(newKey, newVal));
This makes the Map "thread-safe" only from the point-of-view of the JavaFX Application Thread. If the background thread later attempts to read the Map (e.g. map.get(newKey)) there is no guarantee said thread will see the new entry. In other words, it may read null because the entry "doesn't exist" or it may read an old value if one was already present. You could of course fix this by reading on the JavaFX Application Thread as well:
Object val = CompletableFuture.supplyAsync(() -> map.get(key), Platform::runLater).join();
Or even by waiting for the JavaFX Application Thread to finish writing to the Map:
CountDownLatch latch = new CountDownLatch(1);
Platform.runLater(() -> {
// write to map
latch.countDown();
});
latch.await();
// writes to map will be visible to background thread from here
That said, actions by the background thread that happened before the call to runLater will be visible to the JavaFX Application Thread. In other words, a happens-before relationship is created. When scheduling the Runnable to execute on the JavaFX Application Thread eventually some inter-thread communication must occur, which in turn requires synchronization in order to be thread-safe. Looking at the Windows implementation of JavaFX I can't say for certain what this synchronization looks like, however, because it appears to invoke a native method.

Related

Forking with QT

using QtCreator to make a loftier interface to a sofware.
There is basically a set of buttons to tune and inputs, a start and stop job
buttons, my problem comes from an infinite loop that freezes the display so I came up with using fork() so that the loop have to compete with the main program instead of eating up the whole resources (no multithreading), but the program crashes spiting:
[xcb] Unknown sequence number while processing queue
[xcb] Most likely this is a multi-threaded client and XInitThreads has not
been called
[xcb] Aborting, sorry about that.
a.out: ../../src/xcb_io.c:274: poll_for_event: Assertion
`!xcb_xlib_threads_sequence_lost' failed.
the fonction calling the loop is called 'ON', 'OFF' is supposed to exit the forked process.
//in button 'ON' func
ps = fork();
if(getpid() == ps)
{
while(1)
{
strcpy(word, charset(minlength, maxlength, N));
ui->pass->setText(word);//operation on the display
....SNIP
}
}
//In button 'OFF' func
if(getpid() == ps)
exit(0);
I'm really asking what is the correct way of starting a while(1) and be able to break, exit, or return from it while not freezing the window using QT, thanks.
You crash probably here:
ui->pass->setText(word);//operation on the display
as in Qt, you can not change UI from non UI threads directly. Only from signals and slots mechanism.
The proper way to not freeze UI is obviously to compute lengthy operations in another thread.
You can achieve this in several ways:
One is by sub-classing QObject class to create 'worker object' which would perform all heavy operations. You create new QThread object that should live as long as you need your object. And use QObject::moveToThread method to move created object to new thread. To control your worker object you should send signals from object and call it's slots also via signal-slot mechanism. If you call them directly - they will be executed in caller thread (so do not perform stuff like worker->startHeavyJob(); in UI thread). Instead emit signal in UI (emit sigStartHeavyStuff();) and connect it to slot of your worker object (slotDoHeavyStuff();)
if you do not want to bother with this (if operation is pretty small)
- you can use QApplication::processEvents() to process events in UI event loop while going in your infinite while loop.
Another way is to use QtConcurrentRun framework to run function in separate thread which manages itself. Threads are taken from thread pool and are managed by Qt. This approach looks like something you want to do. Though you still will be able to access UI objects only through signals and slots.
I see one big issue in the presented code that is causing your freeze: You never let Qt process anything while you are in the loop. You need to allow Qt to run it's event loop. The easiest way is to use QApplication::processEvents() inside the loop.
I'm also not a fan of a while(1) loop for a couple of reasons. The first of which is that it can eat machine cycles waiting for things to happen. I doubt you really need to run the code as fast as possible, you could probably get away with some sleeping in your loop.
The other issue is that it is hard to break out. A cleaner approach would be something like this
void MyClass::on_pushButton_ON_clicked()
{
MyClass::done = false; // this is a class attribute
while (!MyClass::done) {
QApplication::processEvents();
//...
}
}
void MyClass::on_pushButton_OFF_clicked()
{
MyClass::done = true;
}

Background URLSession on watchOS - what is the cycle?

I have a class with the delegates for a URLSession. I intend to use it with a background configuration. I understand that the handlers are called when a certain event happens, such as didFinishDownloadingTo.
However, I do have the handle function on my ExtensionDelegate class:
func handle( _ handleBackgroundTasks:
Set<WKRefreshBackgroundTask>)
// Sent when the system needs to launch the application in the background
to process tasks. Tasks arrive in a set, so loop through and process each one.
for task in handleBackgroundTasks {
switch task {
case let urlSessionTask as WKURLSessionRefreshBackgroundTask:
I wonder: where should I handle the data I receive after a download? At the didFinishDownloadingTo or at that function on my ExtensionDelegate class, on the appropriate case of the switch statement?
Another question on the same cycle: I read everywhere that one must remember to setTaskCompleted() after going through the background tasks. But I read elsewhere that one should not set a task as completed if the scheduled data transfer hasn't finished. How do I check that?
There is a very good explanation here.enter link description here
It worked when I had an array with my WKURLSessionRefreshBackgroundTask. Then, at the end of my didFinishDownloadingTo, I get the task on that array that has the same sessionIdentifier as the current session.configuration.identifier, and set it as complete.

QThread and QML Locking Up

I have a class, audio_engine_interface, and in main.cpp, I add it to the QML thing.
viewer.rootContext()->setContextProperty("engine", engine);
In audio_engine_interface, I have a audio_engine class, which is computationally intensive—it needs to run on its own thread.
void audio_engine_interface::play()
{
QThread thread;
thread.start();
engine->moveToThread(&thread);
engine->play(); // Will use 100% of CPU
}
However, when I do this, the whole QML thread locks up, meaning I can't pause (pretty important). Am I missing something?
EDIT:
This thread won't mess up anything or access objects from other places. However, it does have a pause function that will need to be called at some point. For what it's worth, the engine is doing pitch shifting.
This is a problem: -
Qthread thread;
Creating a QThread object like this is creating it on the stack. When the function ends, the object will go out of scope and delete the QThread object.
You need to dynamically allocate the object on the heap: -
QThread* thread = new QThread;
Then remember to delete the thread, or set it to delete itself: -
//Qt 5 connect syntax
connect(thread, &QThread::finished, thread, &QThread::deleteLater);
You should also be aware of thread affinity (the thread which an object is running on). I suggest reading this article on how to use QThread properly.
You have so many problems.
when you move to thread your object must not have a parent
your thread object is local variable so it will day immediately when udio_engine_interface::play() end execution
you are invoking you engine->play(); method directly and this means that it will be executed in current thread.
moveToThread means that slots invked by signals connected using default 5th parameter (Qt::AutoConnection) will be queued in event loop of given thread.
The easiest way to fix it is use QtConcurrent:
void audio_engine_interface::play()
{
QtConcurrent::run(engine, &EngineClass::play);
}
Depending what your engine does you should make it thread safe (use mutex locks an so on), without details it is hard to tell, what exactly you should do.

How do I "restart" a JavaFX Application?

I've been coding a simulation in Java and now generate graphs of the results in JavaFX. However, I'm stumped as to how to call the graphs so that when I try to run the simulation (and generate the graphs) for a second time, I don't get the "can't call launch() more than once" error. I read that launch() can only be called once, so what do I need to change to call the graphs successfully on a second run of the simulation?
public class AnswerWorker extends SwingWorker<Void, Integer> {
protected Void doInBackground() throws Exception
{
AMEC.runsimulation();
return null;
}
protected void done()
{
try {
Graphs.launch(Graphs.class, "");
JOptionPane.showMessageDialog(InputGUI.this, AMEC.unsuccesfulpercentage + "% of iterations had trucks that had to sleep over");
AMEC.unsuccesfulpercentage = 0;
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
with a pretty standard graphing class:
public class Graphs extends Application {
#Override public void start(Stage stage) {
....
stage.show();
}
}
Why are you using SwingWorker in a JavaFX application? If your graphs are computed for display in a JavaFX application, there is no reason for you to use the Event Dispatch Thread (AWT). If I'm not mistaken, With the release of JDK 8, the JavaFX Application Thread and the Event Dispatch Thread will become one, so there is no reason (yet) for you to use SwingWorker. If I really am wrong, still, there is no reason for you to use SwingWorker. Although it is possible the coupling of Swing components in JavaFX applications, you should only use EDT when manipulating Swing components, not JavaFX nodes. The following link says this:
...The JavaFX application thread is a different thread from the Swing and AWT Event Dispatch Thread (EDT), so care must be taken when embedding JavaFX code into Swing applications...
Source: http://docs.oracle.com/javafx/2/architecture/jfxpub-architecture.htm
To learn how you can put processes to be done in the background, and also find out which thread is responsible for handling the JavaFX elements, check out this link:
http://docs.oracle.com/javafx/2/threads/jfxpub-threads.htm
Regarding your question, I believe the beginning of a JavaFX application should be called only once. So much is, that when a JavaFX application is started, the thread of main method is captured, and is only returned when the JavaFX application is finalized. Just see the Application DOC (Especially this part). Note also that the life cycle of a JavaFX application is given by the following steps:
Life-cycle
The entry point for JavaFX applications is the Application class. The JavaFX runtime does the following, in order, whenever an application is launched:
Constructs an instance of the specified Application class
Calls the init() method
Calls the start(javafx.stage.Stage) method
Waits for the application to finish, which happens when either of
the following occur:
the application calls Platform.exit()
the last window has been closed and the implicitExit attribute on Platform is true
Calls the stop() method
You might be using the wrong approach. I believe that you should leave your JavaFX application running while you're processing something. Once you have processed what you want in the background, you should make your JavaFX application show the results. The way your JavaFX application run while something is being processed in the background is entirely up to you. Maybe you should hide the window while something is processed, and display it again with your chart done. As I said, this is something you will have to decide. I recommend you to take a look at the documentation of classes referring to the window system, starting with Window, and then Stage.
Any questions, we're here. Good Luck! :)
EDIT:
From what I'm seeing, the user jewelsea is right. Apparently it is not certain that the EDT and the JavaFX Application Thread shall become one (it would be quite interesting if that happened). But anyway, be careful not to confuse yourself with the use of both threads.

Why is ASP.NET HttpContext.Current not set when starting a task with current synchronization context

I was playing around with asynchronous features of .NET a little bit and came up with a situation that I couldn't really explain. When executing the following code inside a synchronous ASP.NET MVC controller
var t = Task.Factory.StartNew(()=>{
var ctx = System.Web.HttpContext.Current;
//ctx == null here
},
CancellationToken.None,
TaskCreationOptions.None,
TaskScheduler.FromCurrentSynchronizationContext()
);
t.Wait();
ctx is null within the delegate. Now to my understanding, the context should be restored when you use the TaskScheduler.FromCurrentSynchronizationContext() task scheduler. So why isn't it here? (I can, btw, see that the delegate gets executed synchronously on the same thread).
Also, from msdn, a TaskScheduler.FromCurrentSynchronizationContext() should behave as follows:
All Task instances queued to the returned scheduler will be executed
through a call to the Post method on that context.
However, when I use this code:
var wh = new AutoResetEvent(false);
SynchronizationContext.Current.Post(s=> {
var ctx = System.Web.HttpContext.Current;
//ctx is set here
wh.Set();
return;
},null);
wh.WaitOne();
The context is actually set.
I know that this example is little bit contrived, but I'd really like to understand what happens to increase my understanding of asynchronous programming on .NET.
Your observations seem to be correct, it is a bit puzzling.
You specify the scheduler as "TaskScheduler.FromCurrentSynchronizationContext()". This associates a new "SynchronizationContextTaskScheduler". Now if you look into this class it uses:
So if the task scheduler has access to the same "Synchronization
Context" and that should reference
"LegacyAspNetSychronizationContext". So surely it appears that
HttpContext.current should not be null.
In the second case, when you use a SychronizationContext (Refer:MSDN Article) the thread's context is shared with the task:
"Another aspect of SynchronizationContext is that every thread has a
“current” context. A thread’s context isn’t necessarily unique; its
context instance may be shared with other threads."
SynchronizationContext.Current is provided by LegacyAspNetSychronizationContext in this case and internally has a reference to HttpApplication.
When the Post method has to invoke registered callback, it calls HttpApplication.OnThreadEnter, which ultimately results in setting of the current thread's context as HttpCurrent.Context:
All the classes referenced here are defined as internal in the framework and is making it a bit difficult to investigate further.
PS: Illustrating that both SynchornizationContext objects in fact point to "LegacyAspNetSynchronizationContext":
I was googling for HTTPContext info some time ago. And I found this:
http://odetocode.com/articles/112.aspx
It's about threading and HTTPContext. There is good explanation:
The CallContext provides a service extremely similar to thread local storage (except CallContext can perform some additional magic during a remoting call). Thread local storage is a concept where each logical thread in an application domain has a unique data slot to keep data specific to itself. Threads do not share the data, and one thread cannot modify the data local to a different thread. ASP.NET, after selecting a thread to execute an incoming request, stores a reference to the current request context in the thread’s local storage. Now, no matter where the thread goes while executing (a business object, a data access object), the context is nearby and easily retrieved.
Knowing the above we can state the following: if, while processing a request, execution moves to a different thread (via QueueUserWorkItem, or an asynchronous delegate, as two examples), HttpContext.Current will not know how to retrieve the current context, and will return null. You might think one way around the problem would be to pass a reference to the worker thread
So you have to create reference to your HTTPContext.Current via some variable and this variable will be adressed from other threads you will create in your code.
Your results are odd - are you sure there's nothing else going on?
Your first example ( with Task ) only works because Task.Wait() can run the task body "inline".
If you put a breakpoint in the task lambda and look at the call stack, you will see that the lambda is being called from inside the Task.Wait() method - there is no concurrency. Since the task is being executed with just normal synchronous method calls, HttpContext.Current must return the same value as it would from anywhere else in your controller method.
Your second example ( with SynchronizationContext.Post ) will deadlock and your lambda will never run.
This is because you are using an AutoResetEvent, which doesn't "know" anything about your Post. The call to WaitOne() will block the thread until the AutoResetEvent is Set. At the same time, the SynchronizationContext is waiting for the thread to be free in order to run the lambda.
Since the thread is blocked in WaitOne, the posted lambda will never execute, which means the AutoResetEvent will never be set, which means the WaitOne will never be satisfied. This is a deadlock.

Resources