Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2005.12.25;
Скачать: [xml.tar.bz2];

Вниз

Как завершить второй поток, работая с СОМ портом.   Найти похожие ветки 

 
MadGhost ©   (2005-11-28 10:09) [0]

Приветствую уважаемые мастера.
Встал следующий вопрос:
Необходимо данные с СОМ порта отсылать на несколько компьютеров, я использовал не компонент а использовать WinAPI функции, второй поток запустил в котором хочу принимать данные.

До конца не добрался, но когда закрываю программу выдает ошибку.


function TForm1.OpenCommPort:boolean;
begin
 hPort := CreateFile("COM1", GENERIC_READ or GENERIC_WRITE, 0, nil,
   OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
 if hPort = INVALID_HANDLE_VALUE then raise Exception.Create("Error opening port");
 if not GetCommState(hPort, Dcb) then
   raise Exception.Create("Error setting port state");
 Dcb.BaudRate := CBR_9600;
 Dcb.Parity := NOPARITY;
 Dcb.ByteSize := 8;
 Dcb.StopBits := ONESTOPBIT;
 if not SetCommState(hPort, Dcb) then raise Exception.Create("Error setting port state");
 if not PurgeComm(hPort, PURGE_TXCLEAR or PURGE_RXCLEAR) then
   raise Exception.Create("Error purging port");

 //ïðîãðàììà äîëæíà îæèäàòü ñîáûòèÿ î ïðèåìå îäíîãî èëè íåñêîëüêèõ
 //áàéò èç ÑÎÌ ïîðòà..
 if not SetCommMask(hPort, EV_RXCHAR) then raise Exception.Create("Error seting port mask");
 result := true;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 CommThread1: TCommThread;
begin
 OpenCommPort;
 StopThread.hEvent := CreateEvent(nil, true, false, nil);
 CommThread1.Create(false);
 h := CommThread1.Handle;
end;


вот, во втором потоке


procedure TCommThread.Execute;
var
 ComStat: TComStat;
 dwMask, dwError, dwRes: DWORD;
 OverRead: array [0..1] of TOverlapped;
 Buf: array [0..$FF] of byte;
 dwRead: DWORD;
begin
 { Place thread code here }
 OverRead[0].hEvent := CreateEvent(nil, True, True, nil);
 OverRead[1].hEvent := StopThread.hEvent;
 FreeOnTerminate := true;
 while not Terminated do
   begin
     if not WaitCommEvent(hPort, dwMask, @OverRead) then
     begin
       if GetLastError = ERROR_IO_PENDING then
         begin
         dwRes := WaitForMultipleObjects(2, @OverRead, FALSE, 500);
           case dwRes of
             WAIT_OBJECT_0:
           end;
         end
       else
         raise Exception.Create("Error waiting port event");
     end;

     if not ClearCommError(hPort, dwError, @ComStat) then
       raise Exception.Create("Error clearing port");
     dwRead := ComStat.cbInQue;
     if dwRead > 0 then
       begin
         if not ReadFile(hPort, Buf, dwRead, dwRead, @OverRead) then
           raise Exception.Create("Error reading port");
       end;
   end;
end;


1.вот таким образом вопрос, как корректно в этом случае завершить второй поток?
2.Как WriteBytes: array of Byte; переделать в String и обратно?

Заранее спасибо. Нужно очень скоро.


 
Leonid Troyanovsky ©   (2005-11-28 10:42) [1]


> MadGhost ©   (28.11.05 10:09)  

> 1.вот таким образом вопрос, как корректно в этом случае
> завершить второй поток?
> 2.Как WriteBytes: array of Byte; переделать в String и обратно?


1. CancelIO ?
2. SetString, Move

--
Regards, LVT.


 
MadGhost ©   (2005-11-28 12:22) [2]

Leonid Troyanovsky ©   (28.11.05 10:42) [1]

1. Да, надо отменить как то операцию чтения из порта, и завершить корректно поток.

2. Поточнее можно, если можно?

заранее благодарен


 
Leonid Troyanovsky ©   (2005-11-28 13:31) [3]


> MadGhost ©   (28.11.05 12:22) [2]


> 1. Да, надо отменить как то операцию чтения из порта, и
> завершить корректно поток.

All I/O operations that are canceled will complete with the error
ERROR_OPERATION_ABORTED. All completion notifications for the I/O operations
will occur normally.

Ну, а, вообще-то, в приведенном коде слишком много, IMHO,
неточностей, чтобы серьезно обсуждать корректность.

> 2. Поточнее можно, если можно?

 SetString(s, PChar(@WriteBytes[0]), Length(WriteBytes))

--
Regards, LVT.


 
Набережных С. ©   (2005-11-28 17:03) [4]


> MadGhost ©


> как корректно в этом случае завершить второй поток

Как минимум - реагировать на факт срабатывания не только первого, но и второго эвента. Причем именно реагировать, а не просто пустышку вставить, как у тебя.


 
Leonid Troyanovsky ©   (2005-11-28 17:34) [5]


> Набережных С. ©   (28.11.05 17:03) [4]

> Как минимум - реагировать на факт срабатывания не только
> первого, но и второго эвента.


А второй-то зачем?

--
Regards, LVT.


 
Набережных С. ©   (2005-11-28 18:16) [6]


> Leonid Troyanovsky ©   (28.11.05 17:34) [5]

Хотя бы потому, что он, вероятно, для того и предназначался. Я бы, скорее всего, использовал сообщения, но это дело вкуса и конкретных обстоятельств.

CancelIO, если мне не изменяет память, необходимо вызывать в том потоке, который инициировал операцию ввода-вывода. Так что в данном случае это будет сродни попытке вытащить себя из болота за волосы.

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


 
Leonid Troyanovsky ©   (2005-11-28 18:38) [7]


> Набережных С. ©   (28.11.05 18:16) [6]


> Хотя бы потому, что он, вероятно, для того и предназначался.
>  Я бы, скорее всего, использовал сообщения, но это дело
> вкуса и конкретных обстоятельств.

А мне, вообще, непонятно, зачем нужен свой поток, который
занимается асинхронным чтением.

> CancelIO, если мне не изменяет память, необходимо вызывать
> в том потоке, который инициировал операцию ввода-вывода.
>  Так что в данном случае это будет сродни попытке вытащить
> себя из болота за волосы.

Ну, а никто не мешал передать в поток уже открытый хендл.
Кроме того, непонятно зачем после WaitCommEvent идет
overlapped ReadFile.

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

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2005-11-28 18:53) [8]


> Набережных С. ©   (28.11.05 18:16) [6]

> CancelIO, если мне не изменяет память, необходимо вызывать
> в том потоке, который инициировал операцию ввода-вывода.
>  Так что в данном случае это будет сродни попытке вытащить
> себя из болота за волосы.


Память не подвела:

The CancelIo function cancels all pending input and output (I/O) operations that were issued by the calling thread for the specified file handle. The function does not cancel I/O operations issued for the file handle by other threads.

Но, есть еще и что-то вроде PurgeComm &PURGE_RXABORT.

Да, и, вообще, автору надо бы msdn почитать.

--
Regards, LVT.


 
Набережных С. ©   (2005-11-28 20:03) [9]


> Leonid Troyanovsky ©

Дополнительный поток может быть нужен по многим причинам. Например, нужно непрерывно следить за портом, одновременно реагируя на действия пользователя. Можно, конечно, реализовать все это и в главном потоке, но это сопряжено с некоторыми неприятными моментами. Я делал такое, мне тогда требовалась максимально быстрая реакция на порт. Беда в том, что Application.ProcessMessage предоставляет не всю функциональность, имеющуюся в штатном режиме обработки сообщений. Некоторые вещи пришлось делать вручную, другие мне тогда были не нужны. А отдельный поток снимает все проблемы. Да мало ли может быть других причин.


> Ну, а никто не мешал передать в поток уже открытый хендл.

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


> Кроме того, непонятно зачем после WaitCommEvent идет
> overlapped ReadFile.

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


> Но, есть еще и что-то вроде PurgeComm &PURGE_RXABORT.

Она не отменяет запросов, сделанных WaitCommEvent. Не вижу, как ее можно применить для решения сформулированной в вопросе задачи.

Вообще говоря, использованная здесь схема не единственная из возможных, но она также применима, как и другие. Есть у нее и свои достоинства, и недостатки. Как и у других. Но к данной теме это, имхо, отношения не имеет, вопрос сформулирован достаточно конкретно.


 
MadGhost ©   (2005-11-29 09:38) [10]

вопрос в другом, как корректно завершить выполнение второго потока? а то EAccessViolation ошибка выскакивает когда закрываю программу.
и все таки не понял как из String в array of Byte; перевести?
Move(String, array of Byte, Length) чето не то делает :(


 
tesseract ©   (2005-11-29 09:59) [11]


> Move(String, array of Byte, Length)



setlength(string,length);
For i:=0 to length-1 do String[i+1]:=chr(buf[i]);

Почти полностью аналогичен move по скорости. Но не оперирует указателями.


 
Набережных С. ©   (2005-11-29 11:06) [12]


> MadGhost ©   (29.11.05 09:38) [10]
> вопрос в другом, как корректно завершить выполнение второго
> потока? а то EAccessViolation ошибка выскакивает когда закрываю
> программу.

См. [4]


 
Leonid Troyanovsky ©   (2005-11-29 11:19) [13]


> Набережных С. ©   (28.11.05 20:03) [9]


> Дополнительный поток может быть нужен по многим причинам.
>  Например, нужно непрерывно следить за портом, одновременно
> реагируя на действия пользователя. Можно, конечно, реализовать
> все это и в главном потоке, но это сопряжено с некоторыми
> неприятными моментами. Я делал такое, мне тогда требовалась
> максимально быстрая реакция на порт. Беда в том, что Application.
> ProcessMessage предоставляет не всю функциональность, имеющуюся
> в штатном режиме обработки сообщений. Некоторые вещи пришлось
> делать вручную, другие мне тогда были не нужны. А отдельный
> поток снимает все проблемы. Да мало ли может быть других
> причин.

Асинхронное чтение и так выполняется в отдельном потоке.
Сделать оперативной реакцию на появление данных в  первичном потоке -
вполне решаемая проблема (ProcessMessage здесь не нужен).

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

Про другие причины я не в курсе.

> > Кроме того, непонятно зачем после WaitCommEvent идет
> > overlapped ReadFile.

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

Согласен, здесь я был не прав.

> > Но, есть еще и что-то вроде PurgeComm &PURGE_RXABORT.

> Она не отменяет запросов, сделанных WaitCommEvent. Не вижу,
>  как ее можно применить для решения сформулированной в вопросе
> задачи.

Для меня это выглядит несколько странно, бо оно должно
terminates all outstanding read operations, но спорить не буду,
бо специалистом по serial communication никогда не был.

> Но к данной теме это, имхо, отношения не имеет, вопрос сформулирован
> достаточно конкретно.

Ну, и слава Богу, что автор понят.

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

Ну, а автору могу лишь посоветовать начать с самого начала, например

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnfiles/html/msdn_serial.asp

Во-всяком случае, я с этого сам бы начал.

--
Regards, LVT.


 
Набережных С. ©   (2005-11-29 12:14) [14]


> Асинхронное чтение и так выполняется в отдельном потоке.
>
> Сделать оперативной реакцию на появление данных в  первичном
> потоке -
> вполне решаемая проблема (ProcessMessage здесь не нужен).
>


> Leonid Troyanovsky ©   (29.11.05 11:19) [13]

А пример можно увидеть?

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

> Чтение же в отдельном собс-ручно построенном потоке, который
> читает синхронно, также не представляет особых проблем,
> как с
> оперативностью, так и с простотой исполнения.

Конечно. И в некоторых случаях это будет наилучшим решением. А в других случаях - совершенно неприемлемым. Я ведь об этом уже писал в конце поста [9].

> Про другие причины я не в курсе.

"не в курсе" и "не существуют" - не синонимы, я надеюсь?

> Для меня это выглядит несколько странно, бо оно должно
> terminates all outstanding read operations, но спорить не
> буду,
> бо специалистом по serial communication никогда не был.

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

PS. Прошу не понять меня превратно. Я вообще не собирался развивать эту тему, если бы не прямой вопрос в [5].


 
Leonid Troyanovsky ©   (2005-11-29 13:02) [15]


> Набережных С. ©   (29.11.05 12:14) [14]

> А пример можно увидеть?


 Например, модальная форма для ожидания хендла.

http://www.rsdn.ru/Forum/Message.aspx?mid=500558&only=1

Понятно, что модальность необязательна.
Было б логично вставить MsgWait в OnIdle, но тогда оно будет мешать
обработке actions & hints.  Т.е., с PostMessage надежней.

Хотя, перечитав исходную посылку (ProcessMessage здесь не нужен),
я понял, что несколько преувелил ;) Но, думаю, что оно показывает, как
оперативно реагировать на появление данных, не мешая пользователю.

> > Чтение же в отдельном собс-ручно построенном потоке, который
> > читает синхронно, также не представляет особых проблем,
>  
> > как с
> > оперативностью, так и с простотой исполнения.
>
> Конечно. И в некоторых случаях это будет наилучшим решением.
>  А в других случаях - совершенно неприемлемым. Я ведь об
> этом уже писал в конце поста [9].

> "не в курсе" и "не существуют" - не синонимы, я надеюсь?

Ясное дело. Однако, другие, IMHO, никто не огласил.

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

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

--
Regards, LVT.


 
Набережных С. ©   (2005-11-29 14:20) [16]


> http://www.rsdn.ru/Forum/Message.aspx?mid=500558&only=1
>
> Понятно, что модальность необязательна.
> Было б логично вставить MsgWait в OnIdle, но тогда оно будет
> мешать
> обработке actions & hints.  Т.е., с PostMessage надежней.
>
>
> Хотя, перечитав исходную посылку (ProcessMessage здесь не
> нужен),
> я понял, что несколько преувелил ;) Но, думаю, что оно показывает,
>  как
> оперативно реагировать на появление данных, не мешая пользователю.
>

Нет, ничего он не показывает. При модальном режиме как раз и крутится цикл с ProcessMessagess, что и является обходом стандартной схемы. Я уж не говорю о том, что придется показывать пользователю форму со всеми вытекающими, которая далеко не всегда допустима. Плюс реакция на объект каждый раз прекращается на время обработки всех сообщений в очереди(с учетом особенностей), что тоже далеко не всегда приемлемо.

Честно говоря, я вообще не понимаю, зачем там модальная форма, когда то же самое делается куда проще:

repeat
 case MsgWaitForMultipleObjects(...) of
   WAIT_OBJECT_0..WAIT_OBJECT_0 + Count - 1: DoEventHandler;
  WAIT_OBJECT)0 + Count: DoMessageHandler;
   else begin
     DoWaitFailureHandler;
     break;
   end;
 end;
until BreakFlag;


Здесь, по крайней мере, можно проверять состояние объекта после обработки каждого отдельного сообщения в очереди.
Но без дополнительной обработки сообщений все равно не обойтись, что и говорилось в [9], и на что вроде как последовали возражения в [13].

Ну а про OnIdle Вы сами все сказали, плюс все то же самое, что я сказал выше.  А если из OnIdle выходить по сообщению, то следующий возврат в нее может наступить очень не скоро, если пользователь пойдет, например, пойти попить пивка.

Так что если есть что-нибудь еще - милосити просим.

> Ясное дело. Однако, другие, IMHO, никто не огласил.

Да ради Бога, на вскидку. Например, я могу повысить потоку приоритет выше остальных и запретить системе повышать его остальным, что обеспечит более быструю реакцию на приход данных. Мне это не подошло, когда я делал упомянутый выше проект, так как требовалась реакция именно главного потока, но в других случаях это эта причина может оказаться важной.
Или вынос поток может быть оправдан с точки зрения оптимизации архитектуры приложения. Можно найти и еще, но и этого достаточно для доказания факта возможности их существования, этих самых других.


 
Leonid Troyanovsky ©   (2005-11-29 14:55) [17]


> Набережных С. ©   (29.11.05 14:20) [16]


> Нет, ничего он не показывает. При модальном режиме как раз
> и крутится цикл с ProcessMessagess, что и является обходом
> стандартной схемы. Я уж не говорю о том, что придется показывать
> пользователю форму со всеми вытекающими, которая далеко
> не всегда допустима. Плюс реакция на объект каждый раз прекращается
> на время обработки всех сообщений в очереди(с учетом особенностей),

Во-первых, модальность здесь факультативна(я говорил).
Во-вторых, дополнительная форма не нужна.
В-третьих, не мешать юзеру - значит, IMHO, обрабатывать (его) сообщения.

> Честно говоря, я вообще не понимаю, зачем там модальная
> форма, когда то же самое делается куда проще:

> repeat
>  case MsgWaitForMultipleObjects(...) of
..
> until BreakFlag;

Такой цикл, как раз, ничего юзеру и не позволит делать.
Что, вероятно, в некоторых случаях, может быть использовано
(скажем, в обработчике контрола, после его disable).

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

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

Ну, и Бог с ним. По-крайней мере, если столкнусь с такой нуждой буду
знать куда обратиться.

--
Regards, LVT.


 
Набережных С. ©   (2005-11-29 16:20) [18]


> > Честно говоря, я вообще не понимаю, зачем там модальная
>
> > форма, когда то же самое делается куда проще:
>
> > repeat
> >  case MsgWaitForMultipleObjects(...) of
> ..
> > until BreakFlag;
>
> Такой цикл, как раз, ничего юзеру и не позволит делать.
> Что, вероятно, в некоторых случаях, может быть использовано
> (скажем, в обработчике контрола, после его disable).

Ну что Вы, в самом-то деле:( Как же не даст? Я же сказал:

> Здесь, по крайней мере, можно проверять состояние объекта
> после обработки каждого отдельного сообщения в очереди.

Я думал, что псевдоним DoMessageHandler достаточно информативен:( В нем мы можем как вызывать Application.ProcessMessages, так и выбирать сообщения по одному через GetMessage, с фильтром или без, или вообще их не выбирать, как Вы правильно заметили.

> Во-первых, модальность здесь факультативна(я говорил).
> Во-вторых, дополнительная форма не нужна.

А без модальности получается тот код, что я привел, с обходом штатной схемы выборки...ну и т.д. Именно по этому поводу и возник вопрос о примере, позволю себе напомнить.

> В-третьих, не мешать юзеру - значит, IMHO, обрабатывать
> (его) сообщения.

Речь шла о том чтобы не мешать юзеру и при этм максимально быстро реагировать на порт, т.е. совместить эти вещи. Опять же - позволю себе напомнить.

> Но, зачем в дополнительном потоке асинхронное чтение я,
> увы, не понял.

Ну как же? А как тогда принудительно прекращать операцию чтения в этом потоке? Мы же уже говорили об этом:( Единственный способ, который я вижу - закрывать хендл порта, но это далеко не всегда приемлемо, как сами понимаете.

Похоже, мы начинаем повторяться, значит, пора заканчивать.


> По-крайней мере, если столкнусь с такой нуждой буду
> знать куда обратиться.

Если Вы имели в виду меня, то буду рад помочь.


 
Leonid Troyanovsky ©   (2005-11-29 18:31) [19]


> Набережных С. ©   (29.11.05 16:20) [18]


> Я думал, что псевдоним DoMessageHandler достаточно информативен:
> ( В нем мы можем как вызывать Application.ProcessMessages,
>  так и выбирать сообщения по одному через GetMessage, с
> фильтром или без, или вообще их не выбирать, как Вы правильно

Так и получится, что не выбирать (или выбирать WM_PAINT) - самое
правильное, а то мы можем снова попасть в тот самый обработчик и т.д.

> А без модальности получается тот код, что я привел, с обходом
> штатной схемы выборки...ну и т.д. Именно по этому поводу

Без модальности форма просто снабжается подобным обработчиком
сообщения. Другого место для Application.ProcessMessages найти не
очень просто.

Вот, если б код Application.Idle можно было бы переписать без участия
приватных полей, то проблемы, вообще бы не было. Т.е., вместо
WaitMessage - MsgWaitFor. Но, к сожалению, Борланд всунул туда
обработку actions & hints, и был неправ.

> быстро реагировать на порт, т.е. совместить эти вещи. Опять

Совмещение и так есть. Вопрос в приоритете.
Т.е., если юзер активен, то ему надо больше.
Если юзер не важен, то это должен быть сервис или драйвер.

> Ну как же? А как тогда принудительно прекращать операцию
> чтения в этом потоке? Мы же уже говорили об этом:(

Да по мне, хоть пусть по таймауту завершится, раз уж самим в буфер
нельзя ничего совать.

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2005-11-29 18:39) [20]


> Набережных С. ©   (29.11.05 16:20) [18]

> Если Вы имели в виду меня, то буду рад помочь.


А.. Ну, да.
Спасибо.

--
Regards, LVT.


 
Набережных С. ©   (2005-11-29 19:44) [21]


> Так и получится, что не выбирать (или выбирать WM_PAINT)
> - самое
> правильное, а то мы можем снова попасть в тот самый обработчик
> и т.д.

Не, не попадем:) Мы-то ведь знаем, в каком состянии находимся, потому и не станем второй раз заходить в нее. Я делал примерно так:

procedure TMForm.MyMessage(...);
begin
 FPort.WaitCommNotification(INFINITY);
end;

И отправлял сообщение через PostMessage. А в самом методе первым делом стоит

 if FWaitState then Exit;
 FWaitState:=true;

а дальше примерно то, что показывал выше. И плюс блокировки акций, двойной кордон получается:)
Так что при нормальном подходе никак мы туда второй раз не попадем, и обрабатывать сможем все сообщения, которые захотим.

> Совмещение и так есть. Вопрос в приоритете.
> Т.е., если юзер активен, то ему надо больше.

По-разному бывает. Например, оператор запустил мониторинг железяки и время от времени смотрит текущее состояние, графики, выводы какие-то делает. Однако при этом главным остается своевременная реакция на приход данных, а пользователь - дело второе, пока он сам не остановит мониторинг.

> Да по мне, хоть пусть по таймауту завершится, раз уж самим
> в буфер
> нельзя ничего совать.

Ну, возможно, и такой подход имеет право на существование, если данные приходят с гарантированными таймаутами, но лично мне он совершенно не нравится.


 
MadGhost ©   (2005-11-30 08:21) [22]

Ну, а автору могу лишь посоветовать начать с самого начала, например
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnfiles/html/msdn_serial.asp
Во-всяком случае, я с этого сам бы начал.

это я читал уже, и делал, есть рабочий код на VC++ но чтобы его доделать до того состояния который мне нужен, ИМХО долго времени займет. Делф ж позволяет при минимуме усилий и времени сделать завершенное приложение которое работает, и которое не особо надо вылизывать.

На сегодняшний день :-) забил на WinAPI, оставил его на прерогативу VC++ и заюзал компоненту CPort-3.0 Ж:-))) + Socket"ы и программка ожила. Главное что быстро :-)

Всем спасибо за участие. Авторам дававшим полезные советы :-) особый решпект, так как кое что почерпнул нового для себя. СПАСИБО.



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2005.12.25;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.56 MB
Время: 0.013 c
1-1133199265
Erick
2005-11-28 20:34
2005.12.25
Работа с ListBox из другой формы


4-1130147239
RainKm
2005-10-24 13:47
2005.12.25
Как узнать пустая ли папка?


1-1133079585
antoxa2005
2005-11-27 11:19
2005.12.25
Уважаемые мастера, подскажите алгаритм получения всех "Child-ов"


1-1133431567
archisan
2005-12-01 13:06
2005.12.25
Internet Explorer :(


2-1133909275
Yozch1
2005-12-07 01:47
2005.12.25
Использование DCU в uses





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский