Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 27.09.2009, 23:38   #1
AnomaliA
Новичок
Джуниор
 
Регистрация: 27.09.2009
Сообщений: 7
По умолчанию Synchronize в DLL

Всем доброго. У меня возникла небольшая проблема с методом Synchronize в DLL. Если коротко о проблеме, то: У меня есть некий компонент, который реализует протакол обмена с устройством через СОМ порт. Данное устройство надо привезать через библиотеку к 1С, НО тут возникла небольшая проблема. В компаненте используются 2 потока, один отправляет сообщение устройству, а второй соответственно, неотвлекая главный поток, принемает ответ от устройства. И тут необюошлось без метода Synchronize, который как извесно не работает в библиотеках. Если ктонибуди решал какнить эту проблему, или есть идеи, буду признателен за помошь )
AnomaliA вне форума Ответить с цитированием
Старый 28.09.2009, 00:42   #2
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

а может стоит поменять логику программы ДЛЛ?
или использовать критические секции?(короче к АПИ спустится)
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 28.09.2009, 09:58   #3
AnomaliA
Новичок
Джуниор
 
Регистрация: 27.09.2009
Сообщений: 7
По умолчанию

к сажелению я не гуру в программировании, поставьте меня на правельный путь и опять-же, менять полностью компоненту не желательно, а использолвание АПИ как я понимаю требует немалой замены кода?

Последний раз редактировалось AnomaliA; 28.09.2009 в 10:00.
AnomaliA вне форума Ответить с цитированием
Старый 28.09.2009, 11:46   #4
sinedSpb
 
Регистрация: 14.08.2009
Сообщений: 8
По умолчанию

Вообщето Synchronize необходим только в том случае если вы обновляете GUI интерфейс не из главного потока приложения. Это связано с механизмом обработки сообщений Windows, все что обновляет визуальные свойства должно прихожить из очереди сообщений . Syncronize добавляет вызов вашего метода в эту очередь. Из DLL это естественно не работает просто так , поскольку в DLL создается своя копия объектов VCL, не могу точно сказать но по моему это как то лечится передачей Application.Handle в DLL. Либо в DLL надо передать CAllBack на вызов Synchronize в основном приложении.
sinedSpb вне форума Ответить с цитированием
Старый 28.09.2009, 12:51   #5
AnomaliA
Новичок
Джуниор
 
Регистрация: 27.09.2009
Сообщений: 7
По умолчанию

Тут есть небольшое но, работать с этой библиотекой будет 1С, а где там взять CAllBack и как его передавать я даже представить немогу.
AnomaliA вне форума Ответить с цитированием
Старый 28.09.2009, 14:15   #6
Black Fregat
Программист
Участник клуба
 
Аватар для Black Fregat
 
Регистрация: 23.06.2009
Сообщений: 1,772
По умолчанию

не морочьте себе голову, до АПИ спускаться не надо, прочитайте в хелпе пример про класс TCriticalSection - вполне хватит
Black Fregat вне форума Ответить с цитированием
Старый 28.09.2009, 16:02   #7
AnomaliA
Новичок
Джуниор
 
Регистрация: 27.09.2009
Сообщений: 7
По умолчанию

Я конечно понимаю что сдесь собираются в основном программисты со стажем, но у меня он очень маленький, и если не трудно ткнуть меня конкрентно что и где надо делать
AnomaliA вне форума Ответить с цитированием
Старый 28.09.2009, 16:42   #8
Black Fregat
Программист
Участник клуба
 
Аватар для Black Fregat
 
Регистрация: 23.06.2009
Сообщений: 1,772
По умолчанию

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

Во-вторых, чтобы тебе помогать конкретно, нужно знать, как оно у тебя сделано. Покажи те куски кода, которые надо засинхронизировать - может, и подскажу чего.
Black Fregat вне форума Ответить с цитированием
Старый 28.09.2009, 17:04   #9
AnomaliA
Новичок
Джуниор
 
Регистрация: 27.09.2009
Сообщений: 7
По умолчанию

Вот выполнение второго потока
Код:
procedure TReadThread.Execute;
var
    CurrentState : TComStat;
    AvaibleBytes,
    ErrCode,
    RealRead     : Cardinal;
    ReadOL       : TOverLapped; {структура для асинхронного чтения}
    Signaled,
    Mask         : DWORD;
    BytesTrans   : DWORD; {не используется для WaitCommEvent}
    bReadable    : Boolean; {готовность к чтению данных}
begin
 with FOwner do begin
  try
    {создание события для асинхронного чтения}
    FillChar(ReadOL, SizeOf(ReadOL), 0);
    ReadOL.hEvent:= CreateEvent(nil, True, True, nil);

    { Маска событий, которые будет отслеживать читающий поток }
    { Пока это только получение символа                       }
    SetCommMask(FHandle, EV_RXCHAR);

    while (not Terminated) and  FConnect do begin {пока порт открыт}
     { Ждем одного из событий }
     WaitCommEvent(FHandle, Mask, @ReadOL);
     {Синхронизация потоков }
     Signaled:= WaitForSingleObject(ReadOL.hEvent, INFINITE);
     if (Signaled  = WAIT_OBJECT_0) then begin
      if GetOverlappedResult(FHandle, ReadOL, BytesTrans, False) then begin
       {после GetOverlappedResult в переменной mask, которая}
       {передавалась в WaitCommEvent, появятся флаги произошедших }
       {событий, либо 0 в случае ошибки.}
       if (Mask and EV_RXCHAR) <> 0 then begin
        {Получаем состояние порта (линий и модема)}
        ClearCommError(FHandle, ErrCode, @CurrentState);

        { Число полученных, но еще не прочитанных байт}
        AvaibleBytes:= CurrentState.cbInQue;
        { Проверка числа доступных байт}
        {ждать любого числа байт}
         bReadable:= AvaibleBytes > 0;

        if bReadable then begin
         {Чистка буфера}
         ZeroMemory(FInBuffer, FInBufSize);
         if ReadFile(FHandle, FInBuffer[0], Min(FInBufSize, AvaibleBytes), RealRead, @ReadOL) then begin
          {сохраняем параметры вызова события}
          FErrCode:= ErrCode;
          FCount  := RealRead;
          {Вызываем событие DoReadPacket. Для синхронизации с VCL}
          {надо вызвать метод Synchronize                        }
          Synchronize(DoReadPacket);
         end;
        end;
       end;
      end;
     end;
    end;

  finally
   {закрытие дескриптора сигнального объекта}
   CloseHandle(ReadOL.hEvent);
   {Сброс события и маски ожидания}
   SetCommMask(FHandle, 0);
  end;
 end;
end;
его идентификатор
Код:
 TReadThread = class(TThread)
  private
   FOwner   : TComPort;
   FInBuffer: TArrayOfByte;{ Входной буфер }
   FErrCode : Cardinal;    { Сохраняет код ошибки }
   FCount   : Integer;     { Реально прочитанное число байт }
  protected
   procedure   Execute; override;
   procedure   DoReadPacket;
  public
   constructor Create(AOwner: TComPort);
   destructor  Destroy; override;
 end;
и если нужно конструктор и диструктор.
Код:
{------------------------------------------------------------------------------}
{ TReadThread::Constructor                                                     }
{------------------------------------------------------------------------------}
constructor TReadThread.Create(AOwner: TComPort);
begin
   { Создаём работающий поток }
   inherited Create(false);        // Нужно false
   FOwner:= AOwner;
   { Создаем новый буфер }
   SetLength(FInBuffer, FOwner.FInBufSize);
end;
{------------------------------------------------------------------------------}
{ TReadThread::Destructor                                                      }
{------------------------------------------------------------------------------}
destructor TReadThread.Destroy;
begin
   { Освобождаем буфер }
   SetLength(FInBuffer, 0);
   inherited Destroy;
end;
Вот тут то и проблема в методе Synchronize, он повисает, а основной поток, который за определённый тайм-аут ждет выполнения DoReadPacket которого напроисходит.
AnomaliA вне форума Ответить с цитированием
Старый 28.09.2009, 19:46   #10
sinedSpb
 
Регистрация: 14.08.2009
Сообщений: 8
По умолчанию

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


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Запуск Load.dll (бывшая Load.exe) в дереве проц-ов, Как запустить прогой на C# .dll-ку kapustin Общие вопросы .NET 10 23.09.2009 22:20
Метод Synchronize класса TThread EdNovice Общие вопросы Delphi 10 01.08.2009 14:47
dll Maxxx 83 Помощь студентам 5 01.02.2009 14:49
DLL michaellos Win Api 1 16.11.2007 21:03