简体   繁体   中英

asyncExec doesn't work for file copy progress

I've a big problem using threads to refresh the graphical user interface built by SWT. I already studied the documentation but can't figure it out.
The task is to copy all files of a folder (only the files, not the subdirectories) to a given target folder.
During the process I calculate the size of the files which already are completed and the remaining time.
And then in every iteration I try to show this information by stepping a progress bar and changing a status label.

The code looks like this:

public class MyClass {
  private Display display;
  private ProgressBar progressBar;
  private Label statusLabel;

  private File inputFile;
  private File outputFolder;

  ...

  public void init(File inputFile, File outputFolder) {
    this.inputFile = inputFile;
    this.outputFolder = outputFolder;

    progressBar.setSelection(0);
    statusLabel.setText("");
  }

  private class CopyFileTask implements Runnable {
    @Override
    public void run() {
      long processedSize = 0L;
      long startTime = System.currentTimeMillis();
      long totalSize = 0L;

      try {
        File[] entries = inputFile.getParentFile().listFiles();

        for (File theEntry : entries) {
          if (theEntry.isFile()) {
            totalSize += theEntry.length();
          }
        }

        for (File theEntry : entries) {
          if (theEntry.isFile()) {
            String entryName = theEntry.getName();
            File file = new File(outputFolder, entryName);

            InputStream fis = new FileInputStream(theEntry);
            FileOutputStream fos = new FileOutputStream(file);

            try {
              byte[] buffer = new byte[1024];
              int len;

              while ((len = fis.read(buffer)) > 0) {
                fos.write(buffer, 0, len);
                processedSize += len;

                showProgressInfo(startTime, processedSize, totalSize);
              }
            } finally {
              try {
                fis.close();
                fos.close();
              } catch (IOException e) {
              }
            }
          }
        }
      } catch (Exception e) {
        Log.error(e);
      }
    }

    private void showProgressInfo(long startTimeMillis, long processedSize, long totalSize) {
      int percent = (int) ((double) processedSize / (double) totalSize * 100.0);
      progressBar.setSelection(percent);

      long elapsedTimeSeconds = (System.currentTimeMillis() - startTimeMillis) / 1000L;
      long remainingSize = totalSize - processedSize;
      long remainingTimeSeconds = (long) ((double) remainingSize
        / (double) processedSize * elapsedTimeSeconds);
      statusLabel.setText(formatFileSize(processedSize)
        + " of "
        + formatFileSize(totalSize)
        + " - Remaining: "
        + secondsToString(remainingTimeSeconds));
    }

    private String formatFileSize(long value) {
      // return value in Bytes, KB, MB, GB
    }

    private String secondsToString(long value) {
      // return value in MM:SS
    }
  }
}

I'm starting the process by clicking a button:

startButton.addListener(SWT.Selection, new Listener() {
  @Override
  public void handleEvent(Event e) {
    display.asyncExec(new CopyFileTask());
  }    
});

And now my problem is that the GUI is freezing until the whole process was completed or in other words - label and progress bar refresh only at the end.

You should start update in selectionListener from different thread:

startButton.addListener(SWT.Selection, new Listener() {

    @Override
    public void handleEvent(Event e) {
        Thread thread = new Thread(new CopyFileTask());
        thread.start();
    }
});

Then post progress updates from current thread to display thread using asyncExec(), for example:

...                         
final long tmpStartTime = startTime;
final long tmpProcessedSize = processedSize;
final long tmpTotalSize = totalSize;
Display.getDefault().asyncExec(new Runnable() {

    @Override
    public void run() {
        showProgressInfo(tmpStartTime, tmpProcessedSize, tmpTotalSize);
    }
});
...                         

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM