Почему множественные параллельные вызовы NetworkManager.addToQueueAndWait мешают друг другу? - PullRequest
0 голосов
/ 11 февраля 2019

Несколько вызовов метода jsonRequest () из разных потоков (Timer-1 и EDT) создают помехи друг другу, и даже один вызов возвращает результат предыдущего вызова

В моем приложении CodeNameOne используется фоновый поток(Таймер-1) для извлечения и отображения данных из службы REST каждую секунду, и это позволяет пользователю выполнять команды, которые также вызывают вызовы REST из потока EDT.

private Map<String, Object> jsonRequest(String url, String body, String cmd, int timeoutMs) {
    long startTs = System.currentTimeMillis();

    try {
        request = new ConnectionRequest();
        request.setReadResponseForErrors(true);
        // request.setTimeout(timeoutMs);
        // Shai: Timeout in Codename One is currently limited to connection timeout and 
        // doesn't apply to read timeout so once a connection is made it will last
        request.setHttpMethod(cmd); 
        request.setPost(cmd.equalsIgnoreCase("POST") || cmd.equalsIgnoreCase("PUT") || cmd.equalsIgnoreCase("PATCH"));
        if (body != null) {
            request.addRequestHeader("Accept", "application/json");
            request.setContentType("application/json");
            request.setRequestBody(body);
            request.setWriteRequest(true);
        }
        request.setUrl(url);
        NetworkManager.getInstance().addToQueueAndWait(request);
        long duration = System.currentTimeMillis() - startTs;
        Log.p(cmd + ": " + url + " " + duration + " ms");

        if (request.getResponseCode() >= 400 || request.getResponseData() == null) {
            Log.p("responseCode=" + request.getResponseCode() + " responseData=" + request.getResponseData());
            return null;
        }
        Log.p(cmd + ": " + url + " " + new String(request.getResponseData()));
        Map<String, Object> result = new JSONParser().parseJSON(new InputStreamReader(new ByteArrayInputStream(request.getResponseData()), "UTF-8"));
        return result;
    } catch (Exception e) {
        problemHandler.handle(cmd, url, e);
    }
    return null;
}

На самом деле результат нескольких вызовов путается.Я ожидаю, что каждый вызов addToQueueAndWait () ожидает правильного результата и возвращает только тогда, когда результат есть.Я заметил, что эта проблема встречается на Android гораздо чаще, чем на iOS или на симуляторе

1 Ответ

0 голосов
/ 12 февраля 2019

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

Нет необходимости использовать поток для опроса, так как сеть уже работает в отдельном потоке (или больше это обычно определяется в методе init(Object)).

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

Хотя лучшим подходом были бы веб-сокеты: https://www.codenameone.com/blog/introducing-codename-one-websocket-support.html

С веб-сокетами серверможет вытолкнуть уведомление об обновлении.Это избавит вас от необходимости постоянно опрашивать сервер.Это экономит время автономной работы устройства и ресурсы на сервере / устройстве.

...