We have a Vaadin 8 application using #Push functionality to push data to the UI which should be loaded asynchronously.
To load the data, we create a Runnable which is executed in an Executor and then makes a callback to a function in the UI/View, where this code is called:
UI ui = getUI();
if (!isAttached() || ui.getSession().hasLock()) {
MainViewComponentImpl.this.componentImpl.getSomeComponent().setVisible(true);
MainViewComponentImpl.this.componentImpl.getSomeComponent().setItems(someHashMap.keySet());
} else {
ui.access(new Runnable() {
#Override
public void run() {
MainViewComponentImpl.this.componentImpl.getSomeComponent().setVisible(true);
MainViewComponentImpl.this.componentImpl.getSomeComponent().setItems(someHashMap.keySet());
}
});
}
If the Runnable where the data is loaded has a Thread.sleep(TimeUnit.SECONDS.toMillis(15)) before doing the callback, then the data is actually pushed into the UI asynchronously, but if it is not, the UI hangs and loads it all together.
My first impression was, that the if/else checks wheather the UI is still being loaded, and if it can add the data to the current load, but even if we uncomment the if-clause and always use the ui.access() method, the data is loaded synchronously. Also, even with the Timeout, it is heavily build-dependent, wheather or not the data is actually loaded asynchronously. After a maven-update, clean project and maven build, most of the time it is asynchronously, but not always.
Is there anyone out there who experienced similar behaviour and made it work?
Thanks
Related
I'm trying to understand these concepts
Event-driven
Asynchronous
non-blocking I/O
Imagine you read from a socket with this pseudo code
void processIO(socket)
{
data = socket.read();
doSomething(data);
}
The read method is used in a blocking mode. That means it does not continue until the data is read. The thread, this is running on is blocked and does not continue until the data is read. doSomething is only called once the data is read. If you did this on a main thread of an app, it would probably not be able to update its UI and would behave like frozen until the data is received.
async void processIO(socket)
{
data = await socket.readAsync();
doSomething(data);
}
This function is asynchronous and it itself calls an asynchronous readAsync() method.
In this way, the thread this runs on is not blocked. It is interrupted at the await statement, and is available for other things in your app to run. Once the data is read, it resumes after the await statement and continues with doing something with the data.
This is one way of doing non-blockig data processing however it is not event driven.
void setupRead(socket)
{
socket.on_data(do_something);
}
void do_something(data)
{
// process data
}
void main()
{
socket = new Socket(111)
setupRead(socket)
while (true) {
processEvents()
}
}
This last example demonstrates event driven IO. You register a callback on some resource to be called when some data arrives. In the mean time your code may do other things or do nothing. This is a non-blocking, asynchronous and event driven approach. The UI get's refreshed and the app may do whatever it needs to.
Event Driven, means you setup event callbacks and wait for the events to happen.
Asynchronous means, you do other stuff while waiting such as refreshing UI, processing user input or read from write from other resources.
Non-blocking means the thread that started the listening, is not blocked until an event arrives, it does whatever else there is to do. Such as handle other events in the mean time.
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.
I'm just getting started with SignalR and I'm wondering if it's a good tool for the task I'm working on.
In short, I have objects with properties that change over time. A timer job runs every once in a while to update these properties. For the sake of explanation, let's say I have MilkJugs with a property "isExpired" that changes once a certain DateTime is hit.
When my timerjob hits a MilkJug and flips it to isExpired = true, I want all clients to get a notification instantly. If a client is looking at seven MilkJugs in Chrome, I want them to see all seven MilkJugs turn yellow (or something like that).
Could I use signalR to "broadcast" these notifications to the clients from the timerJob? I just ran through the chat example they have up and it seems super simple to get working... I think I could do something like this serverside:
public class ChatHub : Hub
{
public void Send(List<MilkJugUpdate> updates)
{
// Call the broadcastMessage method to update milkJugs.
Clients.All.broadcastMessage(updates);
}
}
And then clientside just iterate over the serialized array, updating the appropriate fields in my JS viewModels.
Does this sound about right?
You have got the basic idea there. However there are probably some improvements you could make.
Here I assume you send the message every time you run the timer job. This isn't necessary. You only really need to send a message to the clients if something changes.
Firstly you could handle the onconnected event, and send the current state of the milk jugs.
Now when you run the timer job, you only need to call send if something has changed. Then you send the message to the clients, telling them what has changed. On the clients side, the function handles the change something like the following
Server
public class ChatHub : Hub
{
public override Task OnConnected()
{
//some code here to fetch current state of jugs.
return base.OnConnected();
}
public void JugExpired(MilkJugUpdate update)
{
// Call the broadcastMessage method to update milkJugs.
Clients.All.updateJug(update);
}
}
Client
ChatHub.client.updateJug = function(update) {
// code to update jug here
}
This saves you sending messages to the client if nothing has changed.
Similarly as pointed out in another answer, you can call the client method directly from your timer job, but again, I would only recommend sending updates, rather than the entire state every time.
Absolutely, ShootR does this already (HTML5 multiplayer game). This is also done in the Stock Ticker Sample on nuget.
Ultimately, you can grab the hub context outside of the hub and use it to send messages:
public void MyTimerFunction(object state)
{
GlobalHost.ConnectionManager.GetHubContext<ChatHub>().Clients.All.broadcastMessage(updates);
}
I have a web site which makes frequent requests to an external web service, and I'd like these calls to be async and parallel to avoid blocking and to speed up the site a bit. Basically, I have 8 widgets, each of which has to make its own web call(s).
For some reason, only the first 3 or so of them truly load async, and then the threads don't free up in time, and the rest of the widgets load sequencially. If i could get 3 of them to load in parallel, then 3 more in parallel, then 2 more in parallel, i'd be happy. So the issue is really that the threads aren't freeing up in time.
I'm guessing the answer has to do with some IIS configuration. I'm testing on a non-server OS, so maybe that's part of it.
Edit for #jon skeet:
I'm using reflection to invoke the web calls like this:
output = methodInfo.Invoke(webservice, parameters);
The widget actions (which eventually call the web service) are called via a jquery $.each() loop and the .load function (maybe this causes a bottleneck?). The widget actions are set up as async methods in an async controller.
Here is the code for one of the async methods (they are all set up like this):
public void MarketTradeWidgetAsync()
{
AsyncManager.OutstandingOperations.Increment();
//a bunch of market trade logic
//this eventually calls the web service
PlanUISetting uiSettingMarketQuotesConfig = WebSettingsProviderManager.Provider.GetMarketQuotes(System.Configuration.ConfigurationManager.AppSettings["Theme"], SessionValues<String>.GlobalPlanID, SessionValues<String>.ParticipantID, "MARKETQUOTES");
AsyncManager.OutstandingOperations.Decrement();
}
public ActionResult MarketTradeWidgetCompleted(MarketTradeTool markettradetool)
{
if (Session.IsNewSession)
return PartialView("../Error/AjaxSessionExpired");
else
{
ViewData["MarketData"] = markettradetool;
return PartialView(markettradetool);
}
}
And, like I said, these methods are called via jquery. My thinking is that since the action methods are async, they should give control back to the jquery after they get called, right?
SessionState = "readonly" for the page at hand fixed this issue. Evidently session locking was the issue.
I want to use a SQLite session to demo a wpf application; the session uses test data that has been previously created and saved to a db3 test file. I am binding the context, using code similar to what I use in normal testing - working code.
The difference here is likely that I am building the session factory and loading the test data on a background thread. To the extent that this is the problem, I am wondering if there is a different context than the "thread-static" one I am using.
I can see that the contextual session is available on the background thread. Code is below. Does anyone have a suggestion?
============
background thread code
the context is bound here, and is available when GetCurrentSession() is called
public SqLiteDataProvider()
{
lock (padlock)
{
...
var session = sessionFactory.OpenSession();
CurrentSessionContext.Bind(session);
var pathToMother = FileHelper.GetFilePathFromDirectoryName("src", #"mother.db3");
var conn = (SQLiteConnection)sessionFactory.GetCurrentSession().Connection;
SQLiteDataLoader.ImportData(conn, pathToMother);
_activitySubjectDao = new ActivitySubjectDao(sessionFactory);
}
=============
after the background work has finished
The same ActivitySubjectDao is asked to find some data and fails when it accesses the field:
protected ISession _session { get { return _sessionFactory.GetCurrentSession(); } }
When the dao is constructed on the background thread the session is available.
==============
update
I managed to get this to work by separating out the task of building the session factory from that of loading the test data file, and holding the factory reference in the calling class (and discovered I wasn't generating the SQLite schema in the process, which didn't help even a little).
This seems like a fairly common thing to want to do (building a session factory and fetching data in the background) in a desktop app, so I am still hoping someone is aware of a more elegant solution.
I guess the current session is a [ThreadStatic] variable and thus not available to the new thread?