Good afternoon and hope you are doing great :)
I have method in which I have written new IRunnableWithProgress and I am getting progress bar and all process updates properly no issue at all.
My issue is I can see cancel button on progress bar dailog but after clicking on it nothing is happening. In short code inside if(monitor.isCanceled()){ sysout("Heloooooooooo") } is not executing at all.
please have a look at code sample :
public void runMappers(final EObject profile, final EObject list, final Notification notification) {
this.notification = notification;
getBroker().stopNotification();
final ProgressMonitorDialog pmd = new ProgressMonitorDialog(Display.getCurrent().getActiveShell());
IRunnableWithProgress rwp = new IRunnableWithProgress() {
#Override
public void run(IProgressMonitor monitor) throws InterruptedException {
if (mappers.get(profile) != null) {
int workload = mappers.get(profile).size();
monitor.beginTask("Loading DG list configurations", workload);
Pattern pattern = Pattern.compile("ProfileTo(.*?)ViewMapper");
for (final ProfileToDgListViewMapper mapper : mappers.get(profile)) {
Matcher matcher = pattern.matcher(mapper.toString());
if (matcher.find()) {
monitor.subTask("Loading DG list configuration section " + (matcher.group(1)));
}
mapper.mapProfile(profile, list, notification);
monitor.worked(1);
if(monitor.isCanceled()){
System.out.println("Heloooooooooo");
monitor.done();
Thread.currentThread().interrupt();
return;
}
}
}
monitor.done();
}
};
try {
pmd.run(false, true, rwp);
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InterruptedException e) {
}
getBroker().continueNotification();
}
I tried so many things also some stackoverflow answers, suggesting to perform it with Jobs, But i am not sure how can i call my custome method(with some attributes) in the Job.
Please let me know best suggestion
Thanks in advance ..
Related
I am trying a program with many phidget rfid readers. This test code works fine and I can load up all the readers and have it worked.
Vector phidgetList = manager.getPhidgets();
Enumeration phidgetListEnum = phidgetList.elements();
int count=phidgets.size();
while(phidgetListEnum.hasMoreElements()) {
Phidget phidgetElement = (Phidget) phidgetListEnum
.nextElement();
if (!phidgets.containsKey(phidgetElement.getSerialNumber())) {
RFIDTracking rfi = (RFIDTracking) ct.getTracking("rfid")
.clone();
rfi.setName("rfid clone " + count++);
rfi.detect();
rfi.setCode(phidgetElement.getSerialNumber());
phidgets.put(phidgetElement.getSerialNumber(), rfi);
Thread t = new Thread(rfi);
t.start();
}
}
The problem is when I tried to detect the new readers attached or detached from the system. I used this code
Manager manager;
manager = new Manager();
try {
manager.addAttachListener(new AttachListener() {
public void attached(AttachEvent ae)
{
try
{
System.out.println("attached" + ((RFIDPhidget)ae.getSource()).getSerialNumber());
}
catch (PhidgetException ex) { }
}
});
manager.open();
} catch (PhidgetException exception) {
System.err.println(exception.getErrorNumber()+ exception.getDescription());
}
// Allow the Phidgets time to attach
Thread.sleep(1000);
This code could not detect any reader attachment. I found there is no waitForAttachment(time) in the manager. May I know how to solve this. Thank you in advanced
It's Phidget, but not RFIDPhidget. There is no WaitForAttachment in the manager class because it is not necessary. The previous code works fine, but the wait time must be a little bit longer and the program won't terminate before something is attached.
Manager manager;
manager = new Manager();
try {
manager.addAttachListener(new AttachListener() {
public void attached(AttachEvent ae)
{
try
{
System.out.println("attached" + ((Phidget)ae.getSource()).getSerialNumber());
} catch (PhidgetException ex) { }
}
});
manager.open();
} catch (PhidgetException exception) {
System.err.println(exception.getErrorNumber()+ exception.getDescription());
}
// Allow the Phidgets time to attach
Thread.sleep(1000);
I have the following code which is executed asynchronously. I would like to make it synchronous in order to follow some logical flow but I cannot work out how.
You will see that scanning is set to true to indicate that the method is still working, at the beginning - I then initiate a findPrinters(...) command - this contains a DiscoveryHandler which runs asynchronously - foundPrinter() is called each time an item is discovered. discoveryFinished() is when the discovery process is successfully completed, and discoveryError(...) is called whenever an error occurs.
I rely on something being set in my DiscoveryHandler before I would like to return from this method. Hence why I have while (scanning) underneath it. But this feels like a hack to me, and not the correct way of doing things. I cannot get wait() and notify() working. Can someone tell me what the correct way to do this is please?
private boolean findPrinter(final Context ctx) {
try {
scanning = true;
BluetoothDiscoverer.findPrinters(ctx, new DiscoveryHandler() {
public void foundPrinter(DiscoveredPrinter device) {
if (device instanceof DiscoveredPrinterBluetooth) {
DiscoveredPrinterBluetooth btDevice = (DiscoveredPrinterBluetooth) device;
if (btDevice.friendlyName.startsWith("XXXX")) {
try {
connection = new BluetoothConnection(btDevice.address);
connection.open();
if (connection.isConnected()) {
address = btDevice.address;
}
} catch (Exception ex) {
}
}
}
}
public void discoveryFinished() {
scanning = false;
}
public void discoveryError(String arg0) {
scanning = false;
}
});
} catch (Exception ex) {
}
while (scanning) {}
return false;
}
You could do this with CountDownLatch, which might be the lightest synchronization primitive in java.util.concurrent:
private boolean findPrinter(final Context ctx) {
final CountDownLatch latch = new CountDownLatch(1);
final boolean[] result = {false};
...
BluetoothDiscoverer.findPrinters(ctx, new DiscoveryHandler() {
...
public void discoveryFinished() {
result[0] = true;
latch.countDown();
}
public void discoveryError(String arg0) {
result[0] = false;
latch.countDown();
}
...
}
// before final return
// wait for 10 seconds for the response
latch.await(10, TimeUnit.SECONDS);
//return the result, it will return false when there is timeout
return result[0];
}
There are a bunch of ways you can do this and wait()/notify() is probably not the best since you probably want to return something from your async method. As such I suggest using something like a BlockingQueue. Here is a simplified example of how you can do this:
private boolean findPrinter(final Context ctx) {
final BlockingQueue<?> asyncResult = new SynchronousQueue<?>();
try {
BluetoothDiscoverer.findPrinters(ctx, new DiscoveryHandler() {
public void foundPrinter(DiscoveredPrinter device) {
if (device instanceof DiscoveredPrinterBluetooth) {
DiscoveredPrinterBluetooth btDevice = (DiscoveredPrinterBluetooth) device;
if (btDevice.friendlyName.startsWith("XXXX")) {
try {
connection = new BluetoothConnection(btDevice.address);
connection.open();
if (connection.isConnected()) {
address = btDevice.address;
}
} catch (Exception ex) {
}
}
}
}
public void discoveryFinished() {
asyncResult.put(true);
}
public void discoveryError(String arg0) {
asyncResult.put(arg0);
}
});
} catch (Exception ex) {
}
Object result = asyncResult.take();
if (result instanceof Boolean) {
return (Boolean) result;
} else if (result instanceof String) {
logError((String) result);
}
return false;
}
One problem with using SynchronousQueue here though is that if discoveryFinished()/discoveryError() is called more than once, then the thread executing the code asynchronously will block forever since the SynchronousQueue assumes there will be exactly one take() per every put() and will block if a put() is made without a corresponding take() or vice versa. So if in your case those methods can be called more than once you would probably use a different kind of BlockingQueue instead (see documentation).
Sometimes the doInBackgorund() method of my SwingWorker seems not to be executed, it goes directly to the done() method without saving or printing anything on some of my clients machines, so i suppose it's a random thing , and i can't figure out why. Here 's my code :
public class saveCmdWorker extends SwingWorker<Integer, Integer> {
Order ord;
public saveCmdWorker(Order ord) {
this.ord = ord;
}
#Override
public Integer doInBackground() {
if(999 != ord.getCaissier().getIdCaissier())
saveCmd(ord); // database queries
else
JOptionPane.showMessageDialog(null,"Error",JOptionPane.WARNING_MESSAGE);
if(ord.isIsProd() == false){
try {
// print via serial port
Printer.print(ord, false, Restaurant.numCaisse);
} catch (Exception ex) {
PosO2.errorLogger.log(Level.SEVERE, "Printing error", ex);
}
}
try {
Printer.printFacture(ord, false);
if(btnDuplicata.getForeground() == Color.red)
Printer.printFacture(ord, true);
} catch (Exception ex) {
PosO2.errorLogger.log(Level.SEVERE, "Printing error", ex);
}
return 1;
}
#Override
protected void done() {
try {
btnDuplicata.setForeground(Color.black);
ARendre = 0.0;
ord.clear();
for (int j = 0; j < tab_paiement.size(); j++) {
tab_paiement.get(j).setVisible(true);
}
montantRestant.setBackground(Color.red);
} catch(Exception e) {
PosO2.errorLogger.log(Level.SEVERE, "Refresh Error", e);
}
}
}
I execute this worker via this actionlistener :
ActionListener encaissListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
worker = new saveCmdWorker(cmd);
worker.execute();
}
};
I don't have any logs available so i assume no exception is caught. I saw that a JOptionPane was fired in the doInBackground()(consider as ui modification in an other thread?) but the problem exists when the application doesn't go in the else statement. Can this be the cause of my problems? I don't have this bug on my computer, it just works fine.
As per the SwingWorker documentation (http://docs.oracle.com/javase/7/docs/api/javax/swing/SwingWorker.html#execute()):
SwingWorker is only designed to be executed once. Executing a SwingWorker more than once will not result in invoking the doInBackground method twice.
So, it looks like you need to create a new instance of your subclass each time you want to run the execute method properly.
I have to send a set of files to several computers through a certain port. The fact is that, each time that the method that sends the files is called, the destination data (address and port) is calculated. Therefore, using a loop that creates a thread for each method call, and surround the method call with a try-catch statement for a BindException to process the situation of the program trying to use a port which is already in use (different destination addresses may receive the message through the same port) telling the thread to wait some seconds and then restart to retry, and keep trying until the exception is not thrown (the shipping is successfully performed).
I didn't know why (although I could guess it when I first saw it), Netbeans warned me about that sleeping a Thread object inside a loop is not the best choice. Then I googled a bit for further information and found this link to another stackoverflow post, which looked so interesting (I had never heard of the ThreadPoolExecutor class). I've been reading both that link and the API in order to try to improve my program, but I'm not yet pretty sure about how am I supposed to apply that in my program. Could anybody give a helping hand on this please?
EDIT: The important code:
for (Iterator<String> it = ConnectionsPanel.list.getSelectedValuesList().iterator(); it.hasNext();) {
final String x = it.next();
new Thread() {
#Override
public void run() {
ConnectionsPanel.singleAddVideos(x);
}
}.start();
}
private static void singleAddVideos(String connName) {
String newVideosInfo = "";
for (Iterator<Video> it = ConnectionsPanel.videosToSend.iterator(); it.hasNext();) {
newVideosInfo = newVideosInfo.concat(it.next().toString());
}
try {
MassiveDesktopClient.sendMessage("hi", connName);
if (MassiveDesktopClient.receiveMessage(connName).matches("hello")) {
MassiveDesktopClient.sendMessage(newVideosInfo, connName);
}
} catch (BindException ex) {
MassiveDesktopClient.println("Attempted to use a port which is already being used. Waiting and retrying...", new Exception().getStackTrace()[0].getLineNumber());
try {
Thread.sleep(MassiveDesktopClient.PORT_BUSY_DELAY_SECONDS * 1000);
} catch (InterruptedException ex1) {
JOptionPane.showMessageDialog(null, ex1.toString(), "Error", JOptionPane.ERROR_MESSAGE);
}
ConnectionsPanel.singleAddVideos(connName);
return;
}
for (Iterator<Video> it = ConnectionsPanel.videosToSend.iterator(); it.hasNext();) {
try {
MassiveDesktopClient.sendFile(it.next().getAttribute("name"), connName);
} catch (BindException ex) {
MassiveDesktopClient.println("Attempted to use a port which is already being used. Waiting and retrying...", new Exception().getStackTrace()[0].getLineNumber());
try {
Thread.sleep(MassiveDesktopClient.PORT_BUSY_DELAY_SECONDS * 1000);
} catch (InterruptedException ex1) {
JOptionPane.showMessageDialog(null, ex1.toString(), "Error", JOptionPane.ERROR_MESSAGE);
}
ConnectionsPanel.singleAddVideos(connName);
return;
}
}
}
Your question is not very clear - I understand that you want to rerun your task until it succeeds (no BindException). To do that, you could:
try to run your code without catching the exception
capture the exception from the future
reschedule the task a bit later if it fails
A simplified code would be as below - add error messages and refine as needed:
public static void main(String[] args) throws Exception {
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(corePoolSize);
final String x = "video";
Callable<Void> yourTask = new Callable<Void>() {
#Override
public Void call() throws BindException {
ConnectionsPanel.singleAddVideos(x);
return null;
}
};
Future f = scheduler.submit(yourTask);
boolean added = false; //it will retry until success
//you might use an int instead to retry
//n times only and avoid the risk of infinite loop
while (!added) {
try {
f.get();
added = true; //added set to true if no exception caught
} catch (ExecutionException e) {
if (e.getCause() instanceof BindException) {
scheduler.schedule(yourTask, 3, TimeUnit.SECONDS); //reschedule in 3 seconds
} else {
//another exception was thrown => handle it
}
}
}
}
public static class ConnectionsPanel {
private static void singleAddVideos(String connName) throws BindException {
String newVideosInfo = "";
for (Iterator<Video> it = ConnectionsPanel.videosToSend.iterator(); it.hasNext();) {
newVideosInfo = newVideosInfo.concat(it.next().toString());
}
MassiveDesktopClient.sendMessage("hi", connName);
if (MassiveDesktopClient.receiveMessage(connName).matches("hello")) {
MassiveDesktopClient.sendMessage(newVideosInfo, connName);
}
for (Iterator<Video> it = ConnectionsPanel.videosToSend.iterator(); it.hasNext();) {
MassiveDesktopClient.sendFile(it.next().getAttribute("name"), connName);
}
}
}
I've got an app with several screens. In addition, I have a globally-running timer that occasionally (every minute or so) attempts to refresh their transaction data from a website and store it in a JSONArray (static JSONArray jTransactions).
When you go to the Transaction screen, the first thing it does is populate a ListView with the contents of jTransactions, and it will refresh the displayed info every few seconds. However if the web-thread is currently running, I get null values for everything.
I've got enough coder savvy to know that it's a threading issue, but I'm not experienced enough with JAVA/Android development to know how to handle it. And my Google-fu may be weak but the only answers I found either didn't apply or involved heavy rewriting.
I guess my question is this - how can I alter my code so that there's no direct collision between my activity and the fetch thread?
Also I fully accept that my code is probably ugly; as I said, I'm still learning the platform.
Here's a pared-down version of the thread I'm running:
static int iRefreshTransactions = 30000;
static boolean bRefreshingTransactions = false;
static Calendar cLastRefreshTransactions = null;
final Runnable mRefreshTransactions = new Runnable() {
public void run() {
mHandler.removeCallbacks(this);
Thread T = new tRefreshTransactions();
T.start();
}
};
private class tRefreshTransactions extends Thread {
#Override
public void run() {
bRefreshingTransactions = true;
RetrieveTransactions();
bRefreshingTransactions = false;
handler.sendEmptyMessage(0);
}
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
cLastRefreshTransactions = Calendar.getInstance();
ShowToast("cLastRefreshTransactions(): " + cLastRefreshTransactions.getTime().toLocaleString());
mHandler.postDelayed(mRefreshTransactions, iRefreshTransactions);
}
};
private Handler failhandler = new Handler() {
#Override
public void handleMessage(Message msg) {
// handle the failure somehow
}
};
}
Here's a pared-down version of the RetrieveTransactions() code:
// Retrieve the user's latest transactions from the website.
public boolean RetrieveTransactions() {
String result;
FailureReason = "";
iTransactions = 0;
// Retrieve the Page.
result = GetPage(Url);
// Strip the transactions from the page and convert them to a JSONArray.
try {
String sTransactions = textExtract(result, "var dataTable1Data=", ";\n", 0);
jTransactions = new JSONArray(sTransactions);
iTransactions = jTransactions.length();
return true;
} catch (JSONException e1) {
// Generally if it fails during this, there was no JSONArray to parse (hence no transactions).
FailureReason = "No Transactions Found";
return false;
}
}
And finally here's the pared-down code that displays the transactions in a listview, which is called at activity launch and every 5 seconds or so thereafter:
public void ShowTransactions() {
try {
if (!bRefreshingTransactions) {
if (iTransactions==0) {
return;
}
if (iTransactions==0) return;
List<String> listContents = new ArrayList<String>(iTransactions);
for (int i = 0; i < iTransactions; i++) {
listContents.add(jTransactions.getString(iTransactions - i - 1));
}
lvRecentTransactions.setAdapter(new ArrayAdapterTransactions(MyContext, listContents));
}
} catch (Exception e) {
// Do error stuff here
}
}
Thank you in advance. :)
It seems to be mutual exclusion problem. Make jTransaction synchronized or put the jTransaction variable in synchonized block.
synchronized(jTransactions ){
String sTransactions = textExtract(result, "var dataTable1Data=", ";\n", 0);
jTransactions = new JSONArray(sTransactions);
iTransactions = jTransactions.length();
}
I didn't test the code but I hope synchronization will help you.