Вызвать функцию основного потока из фонового потока - PullRequest
4 голосов
/ 11 августа 2011

Обновление

Я обновил этот вопрос, включив в него исходный код реализации 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();), я установил фоновый поток для выполнения функции обратного вызова.обновить пользовательский интерфейс.Но это не очень хорошая идея, я не хочу, чтобы поток без GUI обновлял GUI.

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

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

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

Ответы [ 2 ]

6 голосов
/ 11 августа 2011

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

Более подробно об этом: Параллелизм в Swing

2 голосов
/ 11 августа 2011

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

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

...