Help!

11 отговора 389 прегледа
#1

Help!

Работя в момента по една програма за управление на модема на телефона ми посредством AT команди, обаче когато написах един цикъл за резетване на телефона посредством команда при неизвестна парола за резет, при който с изпълнение на AT командата при различните комбинации трябва да се пълни един ProgressBar, няколко Label-а да показват последната изпълнена команда, резултатът от нея и т.н., а бутона Start става Stop и т.н. , при стартиране на цикъла програмата просто замръзва и нито мога да натисна Stop бутона, нито мога да я спра по някакъв друг начин, освен да я килна от TaskManager на Windows XP. Къде може да е проблема? Ако трябва да публикувам кода, за да го видите. Писал съм я на Delphi.

Мълчанието е злато, но ние не сме алчни, особено аз!
Отговор
в отговор на MadMax2OOO #2

за тебе дебъг няма ли бре?

мисля че наименованието на програмистката дейност - програмиране е доста подвеждащо. според мене по-подходящо би било "дебъгване". по мои наблюдения това е основната дейност, а измислянето и набирането на кода не отнемат много време.
така както го описваш ми прилича на блокиране в някоя от събитийните функции на главния ти прозорец. доколкото разбирам зависването става още при старт, тоест в инициализацията ти. как я правиш?

Отговор
в отговор на zaphod #3

Има, ама аз си падам малко индианец в дебъгването

Ами ето я въпросната процедура:

procedure BruteReset;
var br : integer;
Key : char;
begin
reset := True;
ResetForm.Button1.Caption := 'Stop';
ResetForm.ProgressBar1.Max := MaxPass(ResetForm.SpinEdit1.Value);
ResetForm.ProgressBar1.Position := 0;
br := 0;
repeat
ResetForm.Label2.Caption := 'Current probing : ' + PhoneCode(br,StrToInt(ResetForm.SpinEdit1.Text));
ResetForm.ProgressBar1.Position := ResetForm.ProgressBar1.Position + 1;
ser.ATCommand('AT*EMAR=' + PhoneCode(br,StrToInt(ResetForm.SpinEdit1.Text)) + ',0');
ResetForm.Label4.Caption := 'Last result : ' + ResResult(ser.ATResult);
ResetForm.Label6.Caption := 'Last command : ' + 'AT*EMAR=' + PhoneCode(br,StrToInt(ResetForm.SpinEdit1.Text)) + ',0';
Inc(br);
until ( ser.ATResult = True ) or ( br = MaxPass(ResetForm.SpinEdit1.Value) );
end;

Малко пояснения: както забелязваш, до repeat всичко е баластра. По-надолу функцията PhoneCode връща комбинацията, която ще се ползва за парола на телефона. ser е тип TBlockSerial. Това е клас от библиотеката за синхронизация, която ползвам - SynaSer, а фунцията му ATCommand връща резултата от AT командата, която се подава на модема. Функцията ResResult е стрингова и връща текст в зависимост от резултата от AT командата ( за целта се използва едно от свойствата на ser - ser.ATResult ). Значи като започне цикъла, Label2 трябва да съдържа текущата комбинация, Label4 - резултата от командата ( положителен или отрицателен ), Label6 - последната изпълнена команда, а прогресбара трябва да се увеличава при всеки цикъл. Е да, ама не. Label-лите въобще не се променят, прогресбара не се пълни, а програмата увисва по неизвестни причини. Ето ти кода, дай ми някакво предложение. ( Преди да направя тази форма, пробвах основата на тази процедура, като визуализирах резултатите на един компонент RichEdit и се получи, макар че програмата работеше, но не можех да натисна никакъв бутон, тоест стоеше като забила, но работеше и резултатите се появяваха в компонента RichEdit )

Мълчанието е злато, но ние не сме алчни, особено аз!
Отговор
в отговор на MadMax2OOO #4

Re: Има, ама аз си падам малко индианец в дебъгването

я сложи вътре в loop-а едно Application.ProcessEvents; (или нещо в тоя стил че на делфи не съм писал от доста време)

Отговор
в отговор на MadMax2OOO #5

Re: Има, ама аз си падам малко индианец в дебъгването

Application.ProcessMessages е нещото което трябва да сложиш след Inc(br);

тогава лабелите и прогресите ще показват правилно

Am I evil?
Yes I am.
Отговор
в отговор на Hateras #6

Re: Има, ама аз си падам малко индианец в дебъгването

Благодаря, получи се, обаче сега възникна друг проблем - как мога да спра цикъла от външна процедура? Става въпрос за това, когато бутона Start стане Stop, понеже за двете събития използвам различни процедури.

Мълчанието е злато, но ние не сме алчни, особено аз!
Отговор
в отговор на MadMax2OOO #7

Re: Има, ама аз си падам малко индианец в дебъгването

има няколко начина, един е със допълнителна проверка в until-a:

Unit1;

Interface;

.....

Implementation;

....

var StopBruteReset : Boolean; //видима за всички в Unit-а

....

procedure BruteReset;
var br : integer;
Key : char;
begin
reset := True;
ResetForm.Button1.Caption := 'Stop';
ResetForm.ProgressBar1.Max := MaxPass(ResetForm.SpinEdit1.Value);
ResetForm.ProgressBar1.Position := 0;
br := 0;
StopBruteReset := False;
repeat
ResetForm.Label2.Caption := 'Current probing : ' + PhoneCode(br,StrToInt(ResetForm.SpinEdit1.Text));
ResetForm.ProgressBar1.Position := ResetForm.ProgressBar1.Position + 1;
ser.ATCommand('AT*EMAR=' + PhoneCode(br,StrToInt(ResetForm.SpinEdit1.Text)) + ',0');
ResetForm.Label4.Caption := 'Last result : ' + ResResult(ser.ATResult);
ResetForm.Label6.Caption := 'Last command : ' + 'AT*EMAR=' + PhoneCode(br,StrToInt(ResetForm.SpinEdit1.Text)) + ',0';
Inc(br);
until ( ser.ATResult = True ) or ( br = MaxPass(ResetForm.SpinEdit1.Value) ) or StopBruteReset;
end;

procedure ButtonStopBruteResetClick(Sender : TObject);
begin
StopBruteReset = True;
end;

други възможности - правиш тред и като ти писне го трепеш, или с message или ...

Am I evil?
Yes I am.
Отговор
в отговор на Hateras #8

Re: Има, ама аз си падам малко индианец в дебъгването

10x

Мълчанието е злато, но ние не сме алчни, особено аз!
Отговор
в отговор на MadMax2OOO #9

Re: Help!

Zdrasti,

Vijdam, 4e ve4e sa ti da li edno ot re6eniata na problema.
Ta za6to ti blokira UI-to?
Za6toto cikala na saob6teniata (message loop ne se izpalniava). Ti blokira6 UI thread-a v cikala za iz4akvane na kakvoto tam 4aka6 (repeat-until). PropcessMessages proveriava i ako ima izteglai edno saob6tenie ot opa6kata i go prepra6ta na porzoreca za koiato e prednazna4eno. Ta za tova kato postavi6 ProcessMessages i programata raboti. No tova ne e na4ina po koito edno prilojenie ot tozi tip bi triabvalo da raboti. Za tova Windows ot 95 (ne sam siguren daje dali ne e o6te ot Win32s) e multithread-ov. Prtavilnoto e da startira6 nov raboten thread (worker thread v koito da pravi6 vsi4kite tezi raboti s modema). Glavniat UI thread triabva da e svoboden za da obslujva UI-to. Tuk triabva da se vnimava oba4e. HWND na kontrolite v windows sa pritejanie na thread-a koito gi sazdava. Ne moje update-va6 kontrol ot thread, koito ne go e sazdal. Obiknovenno tova e glavnia UI thread za6toto osven tova ne moje da se dobavi kontrol kato da6teren na drug kontrol ili vaob6te prozorec ako te sa zasdadeni ot razli4ni threadove. Za tova rabotnia thread triabva da notificira glavnia UI thread za promenite i toi (UI threada) da update-ne kontrolite (progress bar, label-i, button-i i tn). (M/u drugoto za updatvane na butini i menu-ta ima edin component ActionList. Moje da go razgleda6 tova e nai-lesnia na4in za sinhronizirane na butoni i menu-ta sas tekutototo sastoianie na programata)
Dokolkoto si spomniam komponenta za thread vav VCL ima6e method s ime ne6to si *safe* 4rez koito moje da izpalni6 method v glavnia UI thread. Drug na4in (koito m/u drugoto method-a *safe* izpozlva vatre6no) e da izprati6 message na glavnia si prozorec sas SendMessage. Saob6teniata vapreki i send-nati kogato preminavat granicite na threadovete minavat prez opa6kata na saob6teniata i po tozi na4in stava prevkliu4vane na thread-ovete.
Drug nedostatak na Programata ti v momenta e 4e dikato cikli v *repeat-until* cikala iziajda mnogo procesorno vreme naprazno. Tova pravi programata a i windows-a kato cialo muden. Neznam tova *ser* koeto izpozva6 za komunikacia s COM portovete otkade si go vzel no ako e napisano kato horata bi triabvalo da blokira thread-a do momentav koito dadena AT komanda ili kakvoto tam pravi uspee ili propadne ili za niakakav oredelen timeout. Ako klasa ti ima tazi vzamojnost (mnogo e vazmojno da ia niama 6tom kato re6enieto s ProcessMessages raboti) te savetvam da ia izpozva6 v kombinacia s worker thread za da napravi6 programata naistina kakto triabva.
Az li4no ne bih si pusnal programa koiato dokato raboti 6te mi pre4i na rabotata s drugite progami.

HTH
MyNick

Отговор
в отговор на MadMax2OOO #10

Едно малко допълнение

И аз правя нещо подобно.
Само че има няколко разлики:
Инициализацията е писана от колега.
Цялата инициализация я пускам в тред, и отново имам един флаг дето го проверявам в самия тред,
А ако треда нещо запецне - бой по канчето - рядко става и не обичам да го правя ама се случва.
Е да всико е писано на C ама принципите са си същите - и още нещо - всичко се стреля към конзола - за по удобен дебъг.
Пък и конзолата не усвисва :))))

Отговор
в отговор на MyNick #11

Re: Help!

Абе пробвах финалната (?) версия и на моя K6-2 на 500 MHz гълта едва 5 до 10 процента и не ми пречи на другите програми. Като цяло програмата не е нищо особено - терминална програма за модема на телефона ми с функция за разбиване на кода на телефона. Намерих обаче един недостатък на библиотеката за синхронизация, която ползвам - когато пратя AT команда, която като резултат има текст, който е повече от един ред, вместо да показва резултата ред по ред, тя изчаква да се приеме целия резултат и чак тогава го визуализира. Знаеш ли как мога да оправя това?

Мълчанието е злато, но ние не сме алчни, особено аз!

Редактирано от MadMax2OOO на

Отговор