Вызов функции в основном потоке из фонового потока

Обновлять

Я обновил этот вопрос, чтобы включить исходный код реализации Java с использованием предложенного класса SwingWorker, чтобы получить тот же результат, что и в примере с Objective-C. Надеюсь, это поможет будущим искателям приключений.

Document myDoc = ...;
Model myModel = ...;

SwingWorker analyzeDocument = new SwingWorker<Dictionary, Void>() {
    @Override
    public Dictionary doInBackground() {
        return myDoc.analyze();
    }

    @Override
    public void done() {
        try {
            stats = get();
            myModel.setDict(stats);
            myModel.setNeedsDisplay(true);
        } catch(InterruptedException ex) {
            // log
        } catch(ExecutionException ex) {
            // log
        }
    }
};

analyzeDocument.execute();

Исходное сообщение

Я неопытен, когда дело доходит до параллельного программирования, и я надеялся, что кто-то сможет объяснить мне, как я могу этого добиться.

В Objective-C (с GCD) вы можете сделать что-то вроде этого:

 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, NULL), ^{
     NSDictionary *stats = [myDoc analyze];
     dispatch_async(dispatch_get_main_queue(), ^{
       [myModel setDict:stats];
       [myStatsView setNeedsDisplay:YES];
       [stats release];
     });
 });

Этот код выполнит [myDoc analyze] в фоновом потоке после функции обратного вызова для обновления пользовательского интерфейса, который будет выполняться в основном потоке. Другими словами, фоновый поток посылает прерывание основному потоку, добавляя анонимную функцию в очередь основного потока для вызова. Очевидно, что я не смогу использовать анонимные функции в Java, но это не относится к делу.

Я заинтересован в том, чтобы сделать что-то в этом отношении на Java. У меня есть объект Runnable, который выполняет кучу операций в файловой системе. Когда он закончится, я хочу соответствующим образом обновить пользовательский интерфейс.

Чтобы при этом не зависал основной поток (например, backgroundThread.join();), я настроил фоновый поток на выполнение функции обратного вызова для обновления пользовательского интерфейса. Но это не очень хорошая идея, я не хочу, чтобы поток, не относящийся к графическому интерфейсу, обновлял графический интерфейс.

Некоторые другие идеи, о которых я думал, - это опрос, но это похоже на выбрасывание циклов в окно. По тому же мнению, использование фьючерсов также не является ответом. Все это, кажется, противоречит цели асинхронного действия.

Единственное, что я могу придумать, это использовать SwingUtilities.invokeLater из фонового потока и использовать его для обновления графического интерфейса. Но мне любопытно, в каком потоке это будет выполнено.

Может быть, мое восприятие просто искажено, но кажется, что было бы довольно большой частью этого не воспользоваться. Я просто пытаюсь сделать это неправильно?


person Ian Bishop    schedule 10.08.2011    source источник


Ответы (2)


Вы изучали создание и использование объекта SwingWorker? Это позволяет вам легко запускать код в фоновом режиме потока для потока событий, и фактически также является объектом Future, поэтому он может возвращать результат, и вы можете использовать этот результат в своем методе done() для обновления графического интерфейса в событии. нить. Вы даже можете выполнять вызовы потока событий Swing в середине его выполнения с помощью пары методов publish/process.

Подробнее об этом читайте в статье Параллелизм в Swing.

person Hovercraft Full Of Eels    schedule 10.08.2011
comment
Да, это то, что я ищу. Большое спасибо. - person Ian Bishop; 11.08.2011
comment
@IanBishop: Нет, спасибо! Ваше голосование дало мне 1000 баллов за Java, что дало мне золотой значок Java! :) - person Hovercraft Full Of Eels; 11.08.2011
comment
@Hovercraft, Поздравляю, очень заслуженно! :D - person mre; 11.08.2011

Если вы используете Callable<V> вместо Runnable, вы можете вернуть значение.

Также взгляните на класс Executors.

person Luigi Plinge    schedule 10.08.2011
comment
Правильно, это то, что я имел в виду под использованием фьючерсов (download.oracle.com/javase/1,5.0/docs/api/java/util/concurrent/). Можете ли вы уточнить, как это может помочь? - person Ian Bishop; 11.08.2011