Форум программистов, компьютерный форум, киберфорум
Программирование Android
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.82/11: Рейтинг темы: голосов - 11, средняя оценка - 4.82
436 / 161 / 28
Регистрация: 12.12.2020
Сообщений: 1,284

Как подождать выполнения потока

05.01.2021, 23:21. Показов 2154. Ответов 7
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Помогите, плз. Нужно сделать обмен данными с блютус устройством. Код примерно такой:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
       View.OnClickListener oclBtnGetTime = new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                byte[] bytesToSend = {(byte)0xFD,(byte)0xFD};
                myThreadConnected.write(bytesToSend);
                Log.v("myLogs","Отправляем "+Integer.toHexString(Byte.toUnsignedInt(bytesToSend[0]))+" "+Integer.toHexString(Byte.toUnsignedInt(bytesToSend[1])));
                while (myThreadConnected.ReadBytes<2);
                byte[] bytesToRead = new byte[255];
                int br=myThreadConnected.ReadBuffer(bytesToRead);
                Log.v("myLogs","Получили "+Integer.toString(br)+" байт ("+Integer.toHexString(Byte.toUnsignedInt(bytesToRead[0]))+" "+Integer.toHexString(Byte.toUnsignedInt(bytesToRead[1]))+")");
                shHour.setText(bytesToRead[0]);
                shMinute.setText(bytesToRead[1]);
            }
        };
...
    private class ThreadConnected extends Thread {    // Поток - приём и отправка данных
        private final InputStream connectedInputStream;
        private final OutputStream connectedOutputStream;
        private int ReadBytes=0;
        private final byte[] buf = new byte[255];
        public ThreadConnected(BluetoothSocket socket) {
...
        }
        @Override
        public void run() { // Приём данных
            while (true) {
                try {
                    byte[] buffer = new byte[1];
                    int bytes = connectedInputStream.read(buffer);
                    runOnUiThread(new Runnable() { // Вывод данных
                        @Override
                        public void run() {
                            Log.v("myLogs","Получили  байт ("+Integer.toHexString(Byte.toUnsignedInt(buffer[0]))+")");
                            if (ReadBytes<buf.length) buf[ReadBytes++]=buffer[0];
                        }
                    });
                } catch (IOException e) {
                    break;
                }
            }
        }
        public void write(byte[] buffer) {
...
        }
        public int BytesRead() {
            return ReadBytes;
        }
        public int ReadBuffer(byte[] buffer) {
            System.arraycopy(buf,0,buffer,0,255);
            int rb=ReadBytes;
            ReadBytes=0;
            return rb;
        }
    }
Собственно данные отправляются и принимаются (в поток). Но мне нужно получить ответ в том же месте где я отправил данные. Класс потока я сделал, но я так подозреваю что косяк в том что пока выполняется обработчик кнопки - поток не может обработать входящие данные и цикл получается вечным и безрузультатным.
Как исправить ситуацию?
Я тут почитал почитал... через Handler можно вроде как то отправлять сообщения в поток с задержкой отправки.... либо через таймер как то вызывать метод через заданное время... но как то это геморойно, помоему.... как вообще такие ситуации решаются?

Добавлено через 44 минуты
или создать еще один поток и данные ждать в нем? Ну и отправлять заодно можно.... но прием то данных тоже в потоке, он же должен выполняться независимо от обработчика нажатия кнопки. Почему не работает?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
05.01.2021, 23:21
Ответы с готовыми решениями:

Подождать завершения потока
В общем то я начинающий программист c++. Уже третий день сижу над решение задачи: Разработать переносимый (portable) класс ThreadPool....

Заставить pthread подождать, до выполнения условия
есть поток типы pthread. Нужно заставить его подождать, до выполнения условия

Как избежать уничтожения потока после выполнения им своей функции?
создаю несколько потоков for (int i = 0; i &lt; n; i++) BeeThreads = CreateThread(NULL, 0, &amp;Bee_Thread, (CONST LPVOID)i, 0, NULL); ...

7
 Аватар для Чеволек Павук
29 / 24 / 5
Регистрация: 25.12.2018
Сообщений: 614
14.01.2021, 12:46
Ты сначала проверь, действительно ли его нужно ждать, в потоке введи Thread.sleep(5000L) подожди 5 секунд, если результат так и не пришел, значит дело не в потоке.
0
436 / 161 / 28
Регистрация: 12.12.2020
Сообщений: 1,284
16.01.2021, 21:30  [ТС]
Да, проверил. Вот такой код:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
        byte[] bytesToSend = {(byte) 0xFD, (byte) 0xFD};
        myThreadConnected.write(bytesToSend);
 
        Log.v("myLogs", String.format("Отправляем %X %X",bytesToSend[0],bytesToSend[1]));
        try {
            TimeUnit.SECONDS.sleep(5); /* подождем секунду */
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis() + 5000;
        while ((System.currentTimeMillis() < endTime) & (myThreadConnected.ReadBytes < 2)); /* подождем пока буфер не наполнится но не больше 5 сек  */
        if (myThreadConnected.ReadBytes > 1) { /* если в буфере 2 и больше байтов значит ответ есть*/
            byte[] bytesToRead = new byte[255];
            int br = myThreadConnected.ReadBuffer(bytesToRead);
            Log.v("myLogs", String.format("Получили %d байт (%X %X)", br,bytesToRead[0],bytesToRead[1]));
            shTime.setText(GetStringTime(bytesToRead[0],bytesToRead[1]));
        } else Toast.makeText(MainActivity.this, "Нет ответа от Bluetooth-устройства за 1 секунду", Toast.LENGTH_LONG).show();
и ответа нет. Но если тут же нажать кнопку на которую повешено только чтение буфера, то функция благополучно рапортует о том что в буфере два байта и читает их.
Почему так происходит?

Добавлено через 1 час 9 минут
Сделал что бы поток тоже писал в лог когда приходит байт. И получается что я жму кнопку отправки байтов, они уходят, потом ожидание, после того как все время вышло появляется сообщение "нет ответа" и тольок после этого от потока приходит сообщение "получены байты", то есть пока выполняется функция по нажатию кнопки - поток не работает?
0
76 / 52 / 26
Регистрация: 23.01.2019
Сообщений: 134
17.01.2021, 02:33
Привет.
Ожидать выполнения операций приема-передачи в основном потоке - это плохая идея.
При нажатии кнопки следует только передать команду на выполнение действия приема-передачи и завершить обработку нажатия.
После этого отдельный поток должен выполнить это действие и каким-то образом оповестить основной поток о завершении операции и результатах. Я обычно оповещаю через широковещательные сообщения (Broadcast) или пишу интерфейс с Callback функциями.
0
 Аватар для Чеволек Павук
29 / 24 / 5
Регистрация: 25.12.2018
Сообщений: 614
17.01.2021, 16:36
используйте join() и тогда код не продолжит последовательное выполнение, пока ваш поток не завершит работу.
загуглите java ожидание завершения потока, кликайте самую верхнюю ссылку
0
436 / 161 / 28
Регистрация: 12.12.2020
Сообщений: 1,284
17.01.2021, 17:10  [ТС]
Цитата Сообщение от yatrim Посмотреть сообщение
Привет.
Ожидать выполнения операций приема-передачи в основном потоке - это плохая идея.
Плоха идея по идеалогическим соображением, типа как в некоторых языках использование глобальных переменных, оператора goto и слишком большого кода в прерываниях мк или это технически невоможно?
При нажатии кнопки следует только передать команду на выполнение действия приема-передачи и завершить обработку нажатия.
мне было бы удобней весь код что бы был в одном месте - отправили, получили, сделали что надо. А сейчас получается что отправили в одном месте, потом в другом месте подождали ответа и в третьем месте обновили GUI.
После этого отдельный поток должен выполнить это действие и каким-то образом оповестить основной поток о завершении операции и результатах. Я обычно оповещаю через широковещательные сообщения (Broadcast) или пишу интерфейс с Callback функциями.
а можно какой нить пример кода? Или проще чем с классом потока и хендлером для ответа не получится?

Добавлено через 41 секунду
Цитата Сообщение от Чеволек Павук Посмотреть сообщение
используйте join() и тогда код не продолжит последовательное выполнение, пока ваш поток не завершит работу.
так не выйдет. Поток который принимает данные от устройства он постоянно работает.
0
 Аватар для Чеволек Павук
29 / 24 / 5
Регистрация: 25.12.2018
Сообщений: 614
17.01.2021, 18:21
Цитата Сообщение от Alex1126 Посмотреть сообщение
так не выйдет. Поток который принимает данные от устройства он постоянно работает.
Тогда можете попробовать использовать Exchenger myExchanger= new Exchanger<String>()
Тип укажите тот, который хотите передать, далее, там, где вы эти данные передаете в потоке, напишите myExchanger.exchange(сюда вставьте данные для передачи), а в другом своем потоке, где вы эти данные хотите получить, вызовите String data = myExchanger.exchange(сюда вставьте произвольные данные, не важно какие, главное того же типа) , переменная дата получит данные из потока, где вы данные отправляли, поток встанет на ожидание, пока не сможет передать эти данные.
0
436 / 161 / 28
Регистрация: 12.12.2020
Сообщений: 1,284
23.01.2021, 01:41  [ТС]
Всем спасибо. Разобрался. Ожидаю ответа в созданном потоке, а для обновления UI делаю в runOnUiThread
Код примерно такой.
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
public void onGetTimeClick(View v) { 
        byte[] bytesToSend = {(byte) 0xFD, (byte) 0xFD};
        myThreadConnected.write(bytesToSend);
        new Thread(() -> {
            long endTime = System.currentTimeMillis() + 5000;
            while ((System.currentTimeMillis() < endTime) & (myThreadConnected.ReadBytes < 2)); /* подождем пока буфер не наполнится но не больше 5 секунд  */
            if (myThreadConnected.ReadBytes > 1) { /* если в буфере 2 и больше байтов значит ответ есть*/
                byte[] bytesToRead = new byte[255];
                int br = myThreadConnected.ReadBuffer(bytesToRead);
                runOnUiThread(() -> shTime.setText(GetStringTime(bytesToRead[0], bytesToRead[1])));
            } else runOnUiThread(() -> makeText(MainActivity.this, "Нет ответа от Bluetooth-устройства за 5 секунд", Toast.LENGTH_LONG).show());
        }).start();
    }
причем пример кода был всегда у меня перед глазами а я как то усложнял все.
Я так понял что для андройда удобней делать когда пакет данных, приходящий по блютусу, будет иметь заголовок позволяющий его идентифицировать и при приеме данных обрабатывать его не возвращаясь в функцию откуда отправили запрос. В будущем так и буду делать, но тут из принципа хотелось разобраться.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
23.01.2021, 01:41
Помогаю со студенческими работами здесь

Определение времени выполнения потока
подскажите, пожалуйста, как правильно замерять время выполнение потока? ниже приведены мои 2 варианта, возможно что-то неправильно или...

Измерение времени выполнения потока
#include &quot;stdafx.h&quot; #include &lt;clocale&gt; #include &lt;math.h&gt; #include &lt;windows.h&gt; int l, m, n, geo, sum; DWORD WINAPI proizv...

Приостановка выполнения процесса/потока (windows)
Есть запущенный процесс, например, калькулятор или блокнот, известно ID процесса и его имя. Нужно сделать: на форме есть две кнопки, при...

Программа не выводит ничего; вывод потока пустой после выполнения функции
После выполнения одной функции у меня ничего не выводится в консоли через std:cout Main (Rule).CPP std:: vector&lt;...

Определение времени выполнения потока
подскажите, пожалуйста, как правильно замерять время выполнение потока? ниже приведены мои 2 варианта, возможно что-то неправильно или...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Новые блоги и статьи
Программный контроль заполнения реквизита табличной части документа
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: реализовать контроль заполнения реквизита табличной части. . .
wmic не является внутренней или внешней командой
Maks 02.04.2026
Решение: DISM / Online / Add-Capability / CapabilityName:WMIC~~~~ Отсюда: https:/ / winitpro. ru/ index. php/ 2025/ 02/ 14/ komanda-wmic-ne-naydena/
Программная установка даты и запрет ее изменения
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: при создании документов установить период списания автоматически. . .
Вывод данных в справочнике через динамический список
Maks 01.04.2026
Реализация из решения ниже выполнена на примере нетипового справочника "Спецтехника" разработанного в конфигурации КА2. Задача: вывести данные из ТЧ нетипового документа. . .
Функция заполнения текстового поля в реквизите формы документа
Maks 01.04.2026
Алгоритм из решения ниже реализован на нетиповом документе "ВыдачаОборудованияНаСпецтехнику" разработанного в конфигурации КА2, в дополнении к предыдущему решению. На форме документа создается. . .
К слову об оптимизации
kumehtar 01.04.2026
Вспоминаю начало 2000-х, университет, когда я писал на Delphi. Тогда среди программистов на форумах активно обсуждали аккуратную работу с памятью: нужно было следить за переменными, вовремя. . .
Идея фильтра интернета (сервер = слой+фильтр).
Hrethgir 31.03.2026
Суть идеи заключается в том, чтобы запустить свой сервер, о чём я если честно мечтал давно и давно приобрёл книгу как это сделать. Но не было причин его запускать. Очумелые учёные напечатали на. . .
Модель здравосоХранения 6. ESG-повестка и устойчивое развитие; углублённый анализ кадрового бренда
anaschu 31.03.2026
В прикрепленном документе раздумья о том, как можно поменять модель в будущем
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru