I am looking for a way to display images on my ListField from a background thread. First in my drawListRow i try this
path = (String) imagePaths.elementAt(index);
bit = connectServerForImage(path);
g.drawBitmap(xText, y + yText, 80, 200, bit, 0, 0);
but can't scroll smoothly throughout the list, and they say do not do networking or other blocking operations on the UI. But i also try this
private class imgConnection extends Thread
{
public imgConnection() {
super();
}
public void run() {
try {
for (int i = 0; i < imagePaths.size(); i++)
{
final int index = i;
String path = imagePaths.elementAt(index).toString();
bit = connectServerForImage(path);
image.addElement(bit);
}
}
catch (Exception e)
{
System.out.println(e.toString());
}
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
_list.setSize(image.size());
subManager.add(_list);
screen.invalidate();
}
});
}
}
public void drawListRow(ListField list, Graphics g, int index, int y, int w) {
bit = (Bitmap) image.elementAt(index);
g.drawBitmap(xText, y + yText, 80, 200, bit, 0, 0);
}
but nothing happens. Any idea, comments.
You are right, i just started java development 2 weeks ago particularly BB development and i try this link. I want to add a background thread to download image after i got the path url from json return.
first thread:
_connectionthread = new Connection();
_connectionthread.start();
private class Connection extends Thread
{
public Connection()
{
super();
}
public void run() {
try {}
catch (Exception e) {}
}
}
second thread:
_imgConnectionThread = new ImgConnection();
_imgConnectionThread.start();
private class ImgConnection extends Thread
{
public ImgConnection() {
super();
}
public void run() {
try {
}
catch (Exception e)
{
}
}
}
how to update images on ListField?
Answer is based on code from - pastebin.com/90UKTHzP
Terrible code! It's really hard to read and undersand! It looks like you copy pasted several examples from different locations. Also you overriding default behavior with same behavior. Also MainScreen already has VerticalManagerField. Also you're adding list every iteration to manager which will cause IAE. And main one thread is depended on result of second one. They start at the same time, but getting json from server and it's processing could take longer time, so image thread most probably will finish his run without any result.
So main recommendation to fix it - read clean code book! Read more about java development - conventions, multithreading. Read about BB development - UI api, networking.
And finally - start only one thread to get and parse json. After you get it finished - start another thread to get images.
There some minor things that could save you more battery and processor time also - start loading images on demand - when it painted or going to be painted (user scrolls list).
By convention, Java class names start with a capital letter, so imgConnection should really be ImgConnection.
In your sample code, I don't see imgConnection being instantiated anywhere, and I don't see any call to Thread.start(), which is the way a thread i started. Without Thread.start() it is not surprising nothing is happening - the thread is never starting.
Related
Warning: This is my first time using threads and my first time trying out an animation. Please bear with me.
I want to rotate an ImageView. I set up a thread for it:
public class ThreadAnimation extends Thread
{
private ImageView iv;
private RotateTransition rt;
public ThreadAnimation(ImageView iv)
{
this.iv = iv;
}
#Override
public void run()
{
while (true)
{
RotateTransition r = new RotateTransition();
r.setToAngle(360);
r.setCycleCount(1);
r.setDuration(Duration.millis(300));
r.setNode(iv);
r.play();
try
{
sleep(100);
} catch (InterruptedException e)
{
return;
}
}
}
}
I call this inside my controller class, upon pressing a Button.
animation.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle (ActionEvent abschicken)
{
ThreadAnimation thread = null; //ANIMATION PIZZA
if (thread == null)
{
thread = new ThreadAnimation(olivenview);
thread.start();
}
}
});
My ImageView olivenview will rotate just like I wanted it to. However it takes quite a long time until it seems to stop (I can see it because the button triggering it still looks triggered for a while) and when I go ahead to press it a second time afterwards, I get a nonstop error stream with a lot of null pointer exceptions. I am very clueless, can anyone help me out? Is this due to my Thread Setup or does the problem lie somewhere else (in code that I didn't post here)?
I believe you do not need threads for this. Notice the .play() method returns immediately and the animation will run in the background.
That being said, try this.
...
//Create your rotation
final RotateTransition r = new RotateTransition();
r.setToAngle(360);
r.setCycleCount(1);
r.setDuration(Duration.millis(300));
r.setNode(iv);
//When the button is pressed play the rotation. Try experimenting with .playFromStart() instead of .play()
button.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent action) {
r.play();
}
});
...
On an other note I recommend switching to java 8 so that you can use lambda expressions instead of the anonymous class!
I'm using a thread to periodically run a three second background animation.
I adapted the code in question from a Thread Demo example written in Swing and used
it to replace a not quite working earlier version that used both a thread and a task.
My program stops/suspends the thread when either playing a video or running an animation
and starts a new thread when ending the video or animation. This seems to work without
any downside which is why I'm puzzled why my earlier JavaFX searches hadn't turned up
a similar solution to the one I'm using. It seems a rather direct approach for running
short, simple background animations.
Where am I going wrong with this? What am I missing? How would I rewrite this code
using both a Thread and a Task or do I need to?
I should add - the while and run statements are virtually unchanged from the original
and the only significant addition to the Swing code was to add thread.setDaemon( true )
to startThread().
A podcast listener.
// background thread
class BackGround extends Thread {
#Override
public void run() {
while ( suspend.getValue() == false ) {
try {
int r = shared.randInt( 5, 10 );
Thread.sleep( r * 1000 );
} catch ( InterruptedException e ) {
// do nothing
}
if ( suspend.getValue() == false ) {
Platform.runLater( () -> {
int g = shared.cssGradients.length - 1;
g = shared.randInt( 0, g );
gradientColor.set( shared.cssGradients[g] );
Boolean bif = shared.updatePanes( shared.cssGradients[g],
leftPane, rightPane );
});
}
}
}
} // class background
// start thread
public synchronized void startThread() {
thread = new BackGround(); // Thread thread ...defined elsewhere
thread.setDaemon( true );
thread.start();
}
// stop thread
public synchronized void stopThread() {
suspend.set( true );
}
The reason the Task class is useful for JavaFX is that it provides a number of callbacks like succeeded(), failed() or cancelled() and methods like updateProgress() and updateMessage() that will run in the JavaFX Application thread and therefore let you update the UI without Platform.runLater( () -> { ... }); This makes the Task class a perfect choice for doing background tasks like downloading data or long running computations.
However, since your thread simply runs continuously without ever really finishing its work, it doesn't seem that you would need any of the additional functionality a Task would provide you with over a simple Thread.
Still, if you really wanted to convert your code to use a Task, it would look just like this:
class BackGround extends Task<Void> {
#Override
protected Void call() throws Exception {
while (suspend.getValue() == false) {
try {
int r = shared.randInt(5, 10);
Thread.sleep(r * 1000);
} catch (InterruptedException e) {
// do nothing
}
if (suspend.getValue() == false) {
Platform.runLater(() -> {
int g = shared.cssGradients.length - 1;
g = shared.randInt(0, g);
gradientColor.set(shared.cssGradients[g]);
Boolean bif = shared.updatePanes(shared.cssGradients[g],
leftPane, rightPane);
});
}
}
return null;
}
}
// start thread
public synchronized void startThread() {
Task<Void> bg = new BackGround();
Thread taskThread = new Thread(bg);
taskThread.setDaemon(true);
taskThread.start();
}
// stop thread
public synchronized void stopThread() {
suspend.set( true );
}
As you see, it really doesn't make a difference for you, as you don't need anything that a Thread couldn't give you. If however you wanted to have closer communication with the UI thread, e.g. showing a progress bar or showing status updates, then a Task would give you the tools to do that.
I guess its also worth mentioning that the use of a Timeline would be quite elegant for triggering your animations. It would look somewhat like this:
Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(1), new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
int g = shared.cssGradients.length - 1;
g = shared.randInt(0, g);
gradientColor.set(shared.cssGradients[g]);
Boolean bif = shared.updatePanes(shared.cssGradients[g], leftPane, rightPane);
}
}
));
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
The code inside the handle() method is run every second in the JavaFX Application thread. Unfortunately this only lets you set a fixed time between executions, while you seem to want to wait a random amount of time each time.
TL;DR: Using a Thread is ok, because you don't need the additional functionalities of a Task in your use case.
I am currently using JADE to build an agent-based platform to solve scheduling problems. The case is that, a defined behaviour extends AchieveREInitiator doesn't work properly in some specific state of the programme.
This is the behaviour class:
class ACOInitiator extends AchieveREInitiator {
Agent myAgent;
List<Schedule> roundSchedules;
public ACOInitiator(Agent a, ACLMessage msg) {
super(a, msg);
this.myAgent = a;
roundSchedules = new ArrayList<Schedule>();
System.out.println(msg.getContent()); //This is properly printed.
// TODO Auto-generated constructor stub
}
#Override
protected Vector prepareRequests(ACLMessage request) {
System.out.println(request.getContent()); //In some specific state, this is not printed.
Vector v = new Vector(1);
for (int i = 1; i <= Properties.antNum; i++) {
AID aAID = new AID("Ant" + i, AID.ISLOCALNAME);
request.addReceiver(aAID);
aAID = null;
}
v.addElement(request);
return v;
}
#Override
protected void handleAgree(ACLMessage agree) {
try {
roundSchedules.add((Schedule) (agree.getContentObject()));
} catch (UnreadableException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
agree = null;
}
#Override
protected void handleAllResponses(Vector responses) {
Collections.sort(roundSchedules);
Environment.iterSolution = roundSchedules.get(0);
roundSchedules = null;
Environment.setState(Environment.STATE_ITERATION_CHECKING);
responses = null;
myAgent.removeBehaviour(this);
}
}
When the programme is executed, the following results are shown:
Generate solution.
Generate solution.
Iteration #1: 788.0(0.48s) (New best solution)
Generate solution.
Generate solution.
Iteration #2: 809.0(0.12s) r = 1/2
Generate solution.
Generate solution.
Iteration #3: 793.0(0.08s) r = 2/2
......
----- Simulation starts -----
......
#120
Breakdown machines:
Repaired machines:
Incoming jobs: 2-5;
Generate solution.
----- All schemes finished -----
This is unwanted. Apparently, the two Strings to be printed is the same. That's why every iteration in the solution stage, 2 "Generate solution." are printed. However, in the later simulation stage, only 1 "Generate solution." is printed and the programmes goes to the end. It can be inferred that the "prepareRequests" method in not auto called, as in earlier stage.
I'm new to JADE and the problem has bothered me a couple of days. Please help if you are a JADE programmer.
I'm not sure I understand your question or problem but from what I can see the first printout "Generate solution" happens in the constructor:
public ACOInitiator(Agent a, ACLMessage msg) { -> System.out.println(msg.getContent())
the second one in the prepare requests method:
protected Vector prepareRequests(ACLMessage request) {-> System.out.println(msg.getContent())
.
Also remember when interacting with multiple agents the initiator behaviour will wait for a response from all its responder behaviours.
Hope this helps, if it does not, try attaching sniffer diagrams.
I'm new to threading; in fact I'm not even trying to multi- thread the Windows Forms app I'm working on, but all of my searches on this issue lead me to the topic of multithreading. When debugging in Visual Studio 2010 Express, it seems to "jump around" to use the term I've seen others use to describe the same problem. When I let it run, sometimes it runs as expected, other times it just seems to keep running, getting hung up.
In trying to hone my question, I think I need to figure out:
If the timer class calls a method on a different thread, and there isn't an obvious danger of unpredictable instance values/ state corruption in the executing code (there aren't any conditional checks of instance variables etc), why would that method called by the timer appear to behave unpredictably? To me it seems that the code should run synchronously, and if a different thread is used for part of the process, so be it. I can't see where there is opportunity for thread corruption.
When the program starts, it prompts for the timer to be set to run a data download process. After the procedure runs, the timer is set again to a default time, at the end of the procedure. Consistently, the initial timer setting works, and fires as expected, running the data download process... it's that data download method, somewhere within it it goes awry. The last line of code is what sets the timer again, but I can't tell if it's getting hit while debugging it. (jumping around)..
I've added relevant code below... and I stepped into every procedure in my code from the beginning... they all show current thread id 10. This is up to an including the timer firing off, and stopping at a breakpoint at the very next line to execute, which is the data download process. The current thread at that point: 14. I've built the solution before running it/ trying to debug btw. Any ideas?
public partial class frmTradingAppMain : Form
{
private TradingAppDataRunManager drm;
private void frmTradingAppMain_Shown(object sender, EventArgs e)
{
drm = new TradingAppDataRunManager();
drm.StatusChanged += new DataRunManager.DRMStatusChangeHandler(UpdateFormData);
drm.InitializeOrScheduleDataRun();
}
private void UpdateFormData()
{
this.Invoke(new DataRunManager.DRMStatusChangeHandler(UpdateFormDataImpl));
}
private void UpdateFormDataImpl()
{
lblDataDwnLoadManagerStatus.Text = Convert.ToString(drm.Status);
if (drm.Status == DataRunManager.DRMStatus.Inactive)
{
lblNextScheduledDataDownloadDate.Text = "Date not set.";
lblNextScheduledDataDownloadTime.Text = "Time not set.";
}
else
{
lblNextScheduledDataDownloadDate.Text = drm.DateTimeOfNextScheduledDataRun.ToShortDateString();
lblNextScheduledDataDownloadTime.Text = drm.DateTimeOfNextScheduledDataRun.ToShortTimeString();
}
}
}
public abstract class DataRunManager
{
protected DataRunTimer dataRuntimer;
public delegate void DRMStatusChangeHandler();
public event DRMStatusChangeHandler StatusChanged;
public DRMStatusChangeHandler statusChanged;
public void InitializeOrScheduleDataRun()
{
if (DataRunIsAvailable() && UserWouldLikeToPerformDataRun())
RunMainDataProcedure(null);
else
ScheduleDataRun();
}
public void RunMainDataProcedure(object state)
{
start = DateTime.Now;
Status = DRMStatus.Running;
StatusChanged();
GetDataCollections();
foreach (DataCollection dcl in dataCollectionList)
{
dcl.RunDataCollection();
dcl.WriteCollectionToDatabase();
}
PerformDBServerSideProcs();
stop = DateTime.Now;
WriteDataRunStartStopTimesToDB(start, stop);
SetDataRunTimer(DateTimeOfNextAvailableDR());
}
public void ScheduleDataRun()
{
FrmSetTimer frmSetTimer = new FrmSetTimer(DateTimeOfNextAvailableDataRun);
DateTime currentScheduledTimeOfNextDataRun = DateTimeOfNextScheduledDataRun;
DRMStatus currentStatus= Status;
try
{
frmSetTimer.ShowDialog();
DateTimeOfNextScheduledDataRun = (DateTime)frmSetTimer.Tag;
SetDataRunTimer(DateTimeOfNextScheduledDataRun);
}
catch
{
Status = currentStatus;
DateTimeOfNextScheduledDataRun = currentScheduledTimeOfNextDataRun;
}
}
}
public class DataRunTimer
{
System.Threading.Timer timer;
public DataRunTimer(){}
public void SetNextDataRunTime(TimerCallback timerCallback, DateTime timeToSet)
{
if (timer == null)
timer = new System.Threading.Timer(timerCallback);
TimeSpan delayTime = new TimeSpan(timeToSet.Day - DateTime.Now.Day, timeToSet.Hour - DateTime.Now.Hour, timeToSet.Minute - DateTime.Now.Minute,
timeToSet.Second - DateTime.Now.Second);
TimeSpan intervalTime = new TimeSpan(0, 0, 10);
timer.Change(delayTime, intervalTime);
}
public void DataRunTimerCancel()
{
if (timer != null)
timer.Dispose();
}
}
I am using threads in blackberry to perform web service calls. I want to get notified as soon as the call gets a response back. I was using
Handlers
in android. I didnt find anything similar in blackberry.
Here is the code I am using to run the thread
class PrimeRun implements Runnable {
long minPrime;
PrimeRun(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
How can I get a notification after the thread finished running?
How can I do this in blackberry?
Thanks
Added more Information : Thanks for your reply. Its really
informative. Let me explain a bit more on my issue. I have a
webservice call which is running on a thread. As soon as I get the
reply back from server I want to execute the next function(next call
to server) which is based on the response from the previous call.So I need to wait until I get a response back. Also
at them same time I need to show a activity indicator on screen. I was
using handler for this in android. I am looking for something similar
on blackberry.
So your question essentially is this
One thread does the job while the other thread waits for completion
The first thread completes the job and "notifies" the second thread.
This is a simple producer consumer problem. Here is the code how you can solve this.
class JobResult
{
boolean done = false;
}
JobResult result = new JobResult();
class Worker extends Thread
{
JobResult _result;
public Worker( JobResult result )
{
_result = result
}
public void run()
{
// Do some very long job
synchronized( _result )
{
// modify result
_result.done = true;
_result.notify();
}
}
}
public class Waiter extends Thread
{
JobResult _result;
public Waiter( JobResult result )
{
_result = result;
}
public void run()
{
synchroinzed( _result ){
while(! _result.done)
{
this.wait();
}
}
// Wait is over. You can do something now.
}
}
As I got the Zach's question - he asks how to execute some code that involves UI changes (something like showing an info popup or closing the progress popup) upon a background thread completion. On Android a Handler created on the UI thread is often used for that purpose.
In BB you can use another way which is similar to Swing on desktop Java. When you need some code to be executed on the UI thread you wrap it in a Runnable and pass to one of the following methods:
// Puts runnable object into this application's event queue,
// and waits until it is processed.
Application.invokeAndWait(Runnable runnable)
// Puts runnable object into this application's event queue.
Application.invokeLater(Runnable runnable)
// Puts runnable object into this application's event queue
// for repeated execution.
Application.invokeLater(Runnable runnable, long time, boolean repeat)
So the behaviour of the above calls is similar to what Handler.post(Runnable r) (and the like) does.
Note, you can always get a handle to your Application instance by a static call Application.getApplication().
So in the end of a background thread it is safe to do something like this:
Application.getApplication().invokeLater(new Runnable() {
public void run() {
progressScreen.close();
Dialog.alert("I am finished!");
}
});
It is similar to Android's:
handler.post(new Runnable() {
public void run() {
progressScreen.dismiss();
showDialog(DIALOG_TASK_FINISHED_ID);
}
});
Android has a much rich multi threading primitives. But you can achieve the same even in Blackberry with equal elegance. The solution I provide below is essentially the same as previous, but with a minor change. Waiter thread can be replaced with built-in utility to perform painting on UI thread using UiApplicaiton's invokeLater method. You don't actually need to "notify" anyone but just update the UI once a particular task is completed. Check the docs for more info.
Anyway, you can model your code along the lines:
class ProgressScreen extends FullScreen
{
LabelField _label;
public void start()
{
}
public void setMessage( final String message )
{
UiApplication.getApplication(
UiApplication.invokeLater(
new Runnable() {
_label.setText( message );
}
)
);
}
public void dismiss()
{
this.close();
}
}
interface WebserviceTask
{
int STATUS_CONDITIONS_NOT_SATISFIED = -3;
int STATUS_NET_ERR = -2;
int STATUS_FAILURE = -1;
int STATUS_SUCCESS = 0;
public int invoke();
}
public class Updater extends Thread
{
final int NUM_TASKS = 10;
WebServiceTask tasks[] = new WebServiceTask[ NUM_TASKS ];
WebServiceTask tasks[0] = new WebServiceTask(){
public int invoke()
{
int retCode = 0;
// invoke a particular web service
return STATUS_SUCCESS;
}
}
public void run()
{
ProgressScreen progress = new ProgressScreen();
progress.start();
for( int i=0; i < NUM_TASKS; i++ )
{
int retcode;
WebServiceTask t = tasks[i];
retcode = t.invoke();
String mesg;
switch( retcode )
{
case STATUS_SUCCESS: { mesg ="Task successfully completed!";} break;
case STATUS_NET_ERR: { mesg ="Could not connect to network";} break;
}
progress.setMessage(message);
}
progress.dismiss();
}
}
Note that I have provided only the stubs to give you an idea how you may accomplish. Let us know how it goes.