Мастера DELPHI, Delphi programming community Рейтинг@Mail.ru Титульная страница Поиск, карта сайта Написать письмо 
| Новости |
Новости сайта
Поиск |
Поиск по лучшим сайтам о Delphi
FAQ |
Огромная база часто задаваемых вопросов и, конечно же, ответы к ним ;)
Статьи |
Подборка статей на самые разные темы. Все о DELPHI
Книги |
Новинки книжного рынка
Новости VCL
Обзор свежих компонент со всего мира, по-русски!
|
| Форумы
Здесь вы можете задать свой вопрос и наверняка получите ответ
| ЧАТ |
Место для общения :)
Орешник |
Коллекция курьезных вопросов из форумов
KOL и MCK |
KOL и MCK - Компактные программы на Delphi
Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / rsdn.org

 
Чтобы не потерять эту дискуссию, сделайте закладку « предыдущая ветвь | форум | следующая ветвь »
Страницы: 1 2 3 4

Помогите написать работу с потоком [D7]


Kirill ©   (22.08.17 11:31

Добрый день.
Есть программа работы с кассовым аппаратом. В отдельном модуле реализовано хранение чеков в БД, в отдельном работа с web-сервисом (обмен json-данных) с 1С.

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

Вопросы по теме:
1. Как лучше делать выборку неотправленных  данных? По одной записи или все неотправленные и все отправлять? Чтобы фризов в основной программе не было.
2. Как правильно описать Объект потока? В основном потоке уже есть открытое соединение с БД. Надо будет создавать новое соединение?
3. Как правильно вызвать этот поток? При запуске программы (открытии основной формы) или по таймеру запускать (например каждую минуту)?

Delphi 7. БД: Firebird 2.5.7 embed. WS: Synapse и lkJSON.


KilkennyCat ©   (22.08.17 12:20[1]


> Чтобы фризов в основной программе не было.

вроде как, эту проблем уже решает отдельный поток
1. да как угодно. если объем данных небольшой, соединение устойчивое - все сразу.
2. если отправлять по одной записи, то к бд вообще нет смысла обращаться, данные уже есть (внесение в бд же ими делается)
3. если отправлять по одной записи, то сразу при появлении данных. если все сразу - то по завершении кассовой смены.


KilkennyCat ©   (22.08.17 12:21[2]

а еще это может регламентироваться законодательством, сразу или не сразу отправлять.


Kirill ©   (22.08.17 13:26[3]

Не, данные по законодательству отправляются самим аппаратом. А вот в 1С, по-хорошему, надо сразу видеть что оплатили, а что еще нет. А так как есть точки удаленные с нестабильным интернетом, надо предусмотреть что когда чек был пробит инета не было, а потом пытаться, пытаться, пытаться отправить.


Kirill ©   (22.08.17 15:27[4]

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


ухты ©   (22.08.17 16:21[5]

Synapse разве не умеет асинхронно работать?


Kirill ©   (22.08.17 16:34[6]

Нет. ICS асинхронно работает.
Помимо этого хочу разобраться на небольшом но осязаемом примере как правильно использовать потоки.


kilkennycat ©   (22.08.17 17:56[7]


> Можно простенький примерчик, в какой момент получать данные,
>  в какой отправлять данные, получать ответ от веб-сервиса,
>  записывать флаг об успешной отправке и, главное, в какой
> момент вызывать синхронизации с основным потоком, чтобы
> зависаний не было.

Это не простенький примерчик. И все эти моменты определяет программист. Про зависания вообще непонятно.
Имеет смысл сначала всё-таки прочитать книжки по делфи, коих множество, и в коих есть простенькие примерчики отдельных задач. И  тогда вопрос либо отпадет, либо трансформируется в что-то более конкретное.
А вот если бы я писал эту программу, то делал бы ее по ТЗ заказчика.


Kirill ©   (22.08.17 18:00[8]


procedure SendLocalDataToServer;
var
 sthr : TSendThread;
begin
 //
 sthr := TSendThread.Create(True);
 sthr.fhttp := http;
 sthr.Priority := tpLower;
 sthr.FreeOnTerminate := True;
end;

{ TSendThread }

procedure TSendThread.Execute;
var s : string;
begin
 inherited;
 while True do begin
   if Terminated then Break;
   if not DM.SelectDataForSend then begin
     Terminate;
     Break;
   end;
   DM.ibqryThread.First;
   if fhttp.PostPayData(
     DM.ibqryThread.FieldByName('chid').AsInteger,
     DM.ibqryThread.FieldByName('cheque_type').AsInteger,
     DM.ibqryThread.FieldByName('cheque_time').AsDateTime,
     DM.ibqryThread.FieldByName('aw_date').AsDateTime,
     DM.ibqryThread.FieldByName('client').AsString,
     DM.ibqryThread.FieldByName('aw_code').AsString,
     DM.ibqryThread.FieldByName('department').AsInteger,
     DM.ibqryThread.FieldByName('vat_type').AsInteger,
     DM.ibqryThread.FieldByName('quantity').AsFloat,
     DM.ibqryThread.FieldByName('price').AsFloat,
     DM.ibqryThread.FieldByName('summ').AsFloat,
     DM.ibqryThread.FieldByName('vatsumm').AsFloat,
     DM.ibqryThread.FieldByName('summ1').AsFloat,
     DM.ibqryThread.FieldByName('summ2').AsFloat,
     DM.ibqryThread.FieldByName('summ3').AsFloat,
     DM.ibqryThread.FieldByName('summ4').AsFloat,
     DM.ibqryThread.FieldByName('vat18').AsFloat,
     DM.ibqryThread.FieldByName('vat10').AsFloat,
     DM.ibqryThread.FieldByName('vat0').AsFloat,
     s) then begin
     // TODO
     // write code for mark this cheque as posted on server
   end;
 end;
end;


Может подскажете на таком примере правильное направление мысли?


KilkennyCat ©   (22.08.17 21:11[9]

здесь нет мысли ))) лишь небезопасная отправка кучки полей через http-post, и без примера обработки ошибок.


Kirill ©   (23.08.17 08:58[10]

Т.е. простенького примера (можно из комментариев) какой структуры вы бы написали объект потока, в каких процедурах и в какой момент делать выборку данных, отправку в 1с, запись в бд и вызов встроенных процедур самого потока в конференции новичков не дождешься? Н-да... страшно представить чтобы в остальных конференциях сказали и куда послали...
Спасибо, что не отказали.


rrrrrrr ©   (23.08.17 09:20[11]

по коду:
непонятно используется ли отдельная сессия для запроса из потока.

по дизайну:
эй, поток, я вон там оставил для тебя какие-то штуки.
у тебя в юзез мой дм, плюс ты умный, так что сходи туда возьми все что надо (ты знаешь) и сделай что мне надо.


Kirill ©   (24.08.17 00:57[12]

Зря вы так... Спасибо брату, что нашел время и помог мне. Я, конечно, до сих пор не понял как с ним работать, но с его помощью и методом тыка написал такой код, который работает.

constructor TSendThread.Create;
begin
 fhttp := THttpService.Create;
 fTimeout := 1000;
 inherited Create(False);
end;

procedure TSendThread.SendData;
var s : string;
begin
 if not DM.SelectDataForSend then begin
   fTimeout := 5000;
 end
 else begin
   fTimeout:= 1000;
   with DM.ibqryThread do begin
     First;

     if fhttp.PostPayData(
       FieldByName('chid').AsInteger,
       FieldByName('cheque_type').AsInteger,
       FieldByName('cheque_time').AsDateTime,
       FieldByName('awbdate').AsDateTime,
       FieldByName('client').AsString,
       FieldByName('awbcode').AsString,
       FieldByName('department').AsInteger,
       FieldByName('vat_type').AsInteger,
       FieldByName('quantity').AsFloat,
       FieldByName('price').AsFloat,
       FieldByName('summ').AsFloat,
       FieldByName('vatsumm').AsFloat,
       FieldByName('summ1').AsFloat,
       FieldByName('summ2').AsFloat,
       FieldByName('summ3').AsFloat,
       FieldByName('summ4').AsFloat,
       FieldByName('vat18').AsFloat,
       FieldByName('vat10').AsFloat,
       FieldByName('vat0').AsFloat,
       s) then begin
       DM.SetChequePosted(FieldByName('chid').AsInteger);
     end;
   end;
 end;
end;

procedure TSendThread.Execute;
begin
 while not Terminated do begin
   Synchronize(SendData);
   Sleep(fTimeout);
 end;
end;


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

Я от сообщества ожидал, что-то типа такого:

procedure TThread.SendData;
begin
// выборка данных для отправки.
// отправка данных
// если отправка успешна, то фиксируем в бд
end;

procedure TThread.Execute;
begin
 while not Terminated do begin
   Syncronize(SendData);
   Sleep(1000);
 end;
end;


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

Спасибо. Вопрос закрыт


Германн ©   (24.08.17 01:45[13]


> Kirill ©   (22.08.17 16:34) [6]
>
> Нет. ICS асинхронно работает.

Хм. ICS действительно работает как правило асинхронно. В это одна из главных её особенностей (но и синхронно тоже умеет). Но при чем тут ICS?


KilkennyCat ©   (24.08.17 07:25[14]


> Kirill ©
> Что сложного написать тому, кто это знает и главное понимает,
>  эти 10 строк.

они есть практически в любой книжке. что сложного в чтении книжки? Например, у Тейксейры и Пачеко https://www.for-stydents.ru/informatika/delphi/uchebniki/delphi-5-rukovodstvo-razrabotchika-tom-1-osnovnye-metody-i-tehnologii-programmirovaniya.html есть даже "Многопоточный доступ к базе данных". Читали?
И прочитайте https://www.opennet.ru/docs/RUS/smart_question/


Юрий Зотов ©   (24.08.17 07:25[15]

> Kirill ©   (24.08.17 00:57) [12]

> Вопрос закрыт


Вряд ли вопрос закрыт. Дело в том, что в такой редакции второй поток не имеет никакого смысла. Смотрим метод Execute:

procedure TSendThread.Execute;
begin
 while not Terminated do begin
   Synchronize(SendData);
   Sleep(fTimeout);
 end;
end;


Видим, что:

1. Метод SendData вызывается через метод Synchronize - то есть, метод SendData все равно будет выполнен в главном (а не во втором) потоке.

2. Sleep - в данном случае не дает ничего, кроме тормозов (ну разве что разгружает процессор, больше никакого прока от него здесь нет).

3. Больше ничего второй поток не делает. Какой же тогда в нем смысл? Без него все будет работать точно так же.


rrrrrrr ©   (24.08.17 08:40[16]

плюс снова непонятно есть ли у брата отдельная от основной сессия с бд.


Kirill ©   (24.08.17 08:49[17]


> они есть практически в любой книжке. что сложного в чтении
> книжки?

А это из разряда смотрим в книгу, видим фигу. Это проблема моего мышления. Пока я не могу представить в голове, я этого не понимаю и не запоминаю. Я так с фуаном мучался в универе. Я ж говорю, и примеров полно и код рабочий был по потокам, ну не могу понять как он работает. Ответы Юрия тому пример.


> Метод SendData вызывается через метод Synchronize - то есть,
>  метод SendData все равно будет выполнен в главном (а не
> во втором) потоке.

Т.е. вызывать надо без него?


> Sleep - в данном случае не дает ничего, кроме тормозов (ну
> разве что разгружает процессор, больше никакого прока от
> него здесь нет)

Sleep не делает DDOS атаку на web-сервис 1С. Т.е. он отправляет неотправленные чеки с периодичностью каждую секунду, а если в последний раз не было ничего на отправку, то ждет уже 5 сек.

> Больше ничего второй поток не делает. Какой же тогда в нем
> смысл? Без него все будет работать точно так же.

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


> плюс снова непонятно есть ли у брата отдельная от основной
> сессия с бд.

На счет его я не знаю, какая у него структура БД, а у меня нет. Надо новую? А если FB Embeded?


rrrrrrr ©   (24.08.17 08:52[18]

Sleep не делает DDOS

вотэтоповорот. кто бы мог подумать.

На счет его я не знаю, какая у него структура БД, а у меня нет. Надо новую? А если FB Embeded?

уже пофик.


rrrrrrr ©   (24.08.17 08:55[19]

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

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


Страницы: 1 2 3 4 версия для печати

Написать ответ

Ваше имя (регистрация  E-mail 







Разрешается использование тегов форматирования текста:
<b>жирный</b> <i>наклонный</i> <u>подчеркнутый</u>,
а для выделения текста программ, используйте <code> ... </code>
и не забывайте закрывать теги! </b></i></u></code> :)


Наверх

  Рейтинг@Mail.ru     Титульная страница Поиск, карта сайта Написать письмо