0

I have written a program that transmits blocks of data to a device over a TCP socket. As each block is written, the device returns an acknowledgement packet. The program writes the next block after each acknowledgement is received. This write/read sequence is not time/timer based. The program may proceed when the device returns the acknowledgement.

I want to update a JProgressBar. The program works fine, but the JProgressBar does not update as things proceed. The communication process is not timer-based so a timer-based thread to handle the JProgressBar will not work for me, at least that's what I think right now. Every solution that comes near to my need appears to be timer-based. I don't think these will work and my feable attempts to make them work have been entirely unsuccessful.

With this segment, I think I'm close: I'm trying to make the 'EventQueue' thread work to support the JProgressBar, but so far it's not working. I am not an expert on multi-threaded applications, so please be kind and please be specific. I'm really stumped.

int nFWIdx = 0;
final int NOFULLBLOCKS = (int)(arrFIRMWARE.length / BLOCK_INCREMENT);
jprgbarUpload.setMinimum(0);
jprgbarUpload.setMaximum(NOFULLBLOCKS + 1);

for (int blockno = 1; blockno <= NOFULLBLOCKS; blockno++) {
    StringBuilder sb = new StringBuilder();
    for (int loc = nFWIdx; loc < (nFWIdx + BLOCK_INCREMENT); loc++)
        sb.append(arrFIRMWARE[loc])
                .append(UtilityClass.TERMINATOR);
    nFWIdx += BLOCK_INCREMENT;
    byte[] bCOMMAND = sb.toString().getBytes(StandardCharsets.US_ASCII);

    outputstream.write(bCOMMAND);
    outputstream.flush();

    AtomicInteger aiBLOCKNO = new AtomicInteger(blockno);
    java.awt.EventQueue.invokeLater(() -> {
        jprgbarUpload.setValue(aiBLOCKNO.get());
    });

    boolean blnISACKRCVD = false;
    byte[] bINMESSAGE = new byte[TCP_SINGLE_FRAME_SIZE];
    while (!blnISACKRCVD) {
        int iSTREAMREAD = bufferedinputstream.read(bINMESSAGE);
        String sSTREAMREAD  = (new String (bINMESSAGE)).trim();
        if (sSTREAMREAD.length() == FIRMWARE_ACK_MESSAGE.length())
        {
            blnISACKRCVD = true;
        }
    }
}
  • 1
    `"Every solution that comes near to my need appears to be timer-based."` -- no, the most common solution, and the one that will work for you is to use a background thread, a SwingWorker. Also look at my answer [here](http://stackoverflow.com/a/9351702/522444). But set the SwingWorker's progress property, and listen to that property using a PropertyChangeListener, as per [MadProgrammer's answer to a similar question](http://stackoverflow.com/a/13095992/522444). – Hovercraft Full Of Eels Aug 31 '16 at 20:35
  • Also please have a look at [my answer to this question](http://stackoverflow.com/a/25694838/522444). – Hovercraft Full Of Eels Aug 31 '16 at 20:36
  • Swing/AWT apps usually are very asynchronous, but you're not thinking in that mode. Here's how I would do it: Pool worker thread performs I/O, and keeps a shared variable up-to-date with how much data have been moved. Timer fires every two seconds. The timer event handler checks the shared variable, and updates the progress bar regardless of whether there has been any progress or not. When shared variable shows I/O is complete, timer event handler removes progress bar, and cancels the timer. – Solomon Slow Aug 31 '16 at 20:59
  • @jameslarge I like your suggestion; it is novel and instructive. I think I can conceptualize and manifest this . . . And yes, this being my first foray into asynchronous operations, I can confirm I definitely am not thinking in this way. I am a neophyte to multi-threaded applications. Thanks. – paulstgeorge Aug 31 '16 at 22:19
  • @hovercraft-full-of-eels your links to previous answers that justify marking my question as an exact duplicate could likely be helpful to me someday, but today I find them a bit difficult to extract guidance. I'll get there, I guess - a great deal of noodling lies ahead for me. Thanks. – paulstgeorge Aug 31 '16 at 22:19
  • Got it. Turned out the final solution was pretty simple. No timers or class-level variables needed. As you stated, I just needed to structure a proper doInBackground method of a SwingWorker thread. The effort, for me was a bit Herculean, but the end result is fairly elegant, high performing, and easy to understand. Thanks – paulstgeorge Sep 02 '16 at 19:39

0 Answers0