Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
 OLE-объект в потоке  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 2404
Странная ситуация.
В доп. потоке происходит зависание при создании объекта, тогда как в "главном" потоке всё работает отлично.

Код потока:
var
  v: Variant;
begin
  CoInitialize( nil );
  v := CreateOleObject( 'AddIn.FprnM45' ); // Здесь виснет
end;


D6.

Если кто сталкивался - откликнитесь, пожалуйста, ткните куда надо. Спасибо.

Да, на всякий случай. Это драйвер АТОЛ ККМ.
Если загрузить TLB-обертку ActiveX, то происходит то же самое:

В доп. потоке виснет:
begin
  CoInitialize( nil );
  ECR := TFprnM45.Create( nil ); // Здесь виснет
end;


В основном всё отлично создается и работает:
procedure TfrmMain.FormCreate(Sender: TObject);
begin
  // CoInitialize( nil ); // и без этой строки - в гл. потоке он не нужет
  ECR := TFprnM45.Create( nil ); // Отрабатывает отлично
end;


Пол дня уже убил. Не знаю, что и думать.
1 сен 15, 22:08    [18097313]     Ответить | Цитировать Сообщить модератору
 Re: OLE-объект в потоке  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 2404
Да, мне надо обязательно в доп. потоке юзать этот объект. В главном я так проверил - для тестов.
1 сен 15, 22:09    [18097315]     Ответить | Цитировать Сообщить модератору
 Re: OLE-объект в потоке  [new]
чччД
Guest
YuRock,

а в двух параллельных процессах - не блокируется?
1 сен 15, 22:24    [18097349]     Ответить | Цитировать Сообщить модератору
 Re: OLE-объект в потоке  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 2404
чччД,

Нет. Я и не создаю его в двух потоках - я ж говорю, я в главном только для тестов создал, чтоб проверить, не зависнет ли в нём. Мне только в дополнительном нужен.

У меня такое подозрение закралось.
Дело в том, что когда в моем доп. потоке приходит время создать этот объект, то главный поток висит - он ждет, пока выполнится операция из очереди, которую выполняет как раз этот доп. поток.
Может этот объект как-то обращаться к главному потоку приложения в этот момент создания себя? Если да - то всё понятно.. Возможно такое вообще?
1 сен 15, 22:50    [18097430]     Ответить | Цитировать Сообщить модератору
 Re: OLE-объект в потоке  [new]
krapotkin
Member

Откуда: Екатеринбург
Сообщений: 539
тоже работал с ним, только в главном потоке...

в принципе, что ему может помешать слазить "на минутку" в главный поток ((
1 сен 15, 23:10    [18097510]     Ответить | Цитировать Сообщить модератору
 Re: OLE-объект в потоке  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 9873
krapotkin
в принципе, что ему может помешать слазить "на минутку" в главный поток ((
Незнание, где именно главный поток?

2Автор. А если в обычном консольном приложении? Что-то типа такого
{$APPTYPE CONSOLE}
program Project1;

procedure Test;
begin
  CreateOleObject( 'AddIn.FprnM45' ); // Здесь виснет
end;

begin
  CoInitialize(nil);
  Test;
end.
1 сен 15, 23:33    [18097603]     Ответить | Цитировать Сообщить модератору
 Re: OLE-объект в потоке  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 2404
_Vasilisk_,

{$APPTYPE CONSOLE}
program Project1;

uses Windows, ComObj, Activex;

procedure Test;
begin
  CreateOleObject( 'AddIn.FprnM45' ); // Здесь виснет
end;

begin
  CoInitialize(nil);
  Test;
  MessageBox( 0, 'Test', '', 0 );
end.


Всё работает, MessageBox сразу появляется.
1 сен 15, 23:53    [18097703]     Ответить | Цитировать Сообщить модератору
 Re: OLE-объект в потоке  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 2404
В смысле, ничего не виснет. Это же главный поток.
1 сен 15, 23:54    [18097707]     Ответить | Цитировать Сообщить модератору
 Re: OLE-объект в потоке  [new]
Relic Hunter
Member

Откуда: AB
Сообщений: 6222
YuRock,

А так?

CoInitializeEx with COINIT_MULTITHREADED
2 сен 15, 00:02    [18097736]     Ответить | Цитировать Сообщить модератору
 Re: OLE-объект в потоке  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 2404
Relic Hunter
YuRock,

А так?

CoInitializeEx with COINIT_MULTITHREADED

Это никак не влияет, я пробовал.
2 сен 15, 00:05    [18097743]     Ответить | Цитировать Сообщить модератору
 Re: OLE-объект в потоке  [new]
YuRock
Member

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

{$APPTYPE CONSOLE}
program aaa;

uses Windows, ComObj, Activex, Classes;

var
  hEndEvent: THandle;

procedure Test;
begin
  CreateOleObject( 'AddIn.FprnM45' );
end;

type
  TMyThread = class( TThread )
  protected
    procedure Execute; override;
  end;

procedure TMyThread.Execute;
var
  v: Variant;
begin
  CoInitializeEx( nil, COINIT_MULTITHREADED );
  v := CreateOleObject( 'AddIn.FprnM45' ); // Здесь уже не виснет
  SetEvent( hEndEvent );
end;

begin
  hEndEvent := CreateEvent( nil, True, False, nil );

  with TMyThread.Create( False ) do begin
    WaitForSingleObject( hEndEvent, INFINITE );
    Free;
  end;

  MessageBox( 0, 'Test', '', 0 );
  CloseHandle( hEndEvent );
end.
2 сен 15, 00:09    [18097758]     Ответить | Цитировать Сообщить модератору
 Re: OLE-объект в потоке  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 2404
Да, а из оконного виснет.

Вот окончательный код консольного, где не виснет:
{$APPTYPE CONSOLE}
program Project1;

uses Windows, ComObj, Activex, Classes;

var
  hEndEvent: THandle;

type
  TMyThread = class( TThread )
  protected
    procedure Execute; override;
  end;

procedure TMyThread.Execute;
var
  v: Variant;
begin
  CoInitialize( nil );
  v := CreateOleObject( 'AddIn.FprnM45' ); // Здесь уже не виснет
  SetEvent( hEndEvent );
end;

begin
  hEndEvent := CreateEvent( nil, True, False, nil );

  with TMyThread.Create( False ) do begin
    WaitForSingleObject( hEndEvent, INFINITE );
    Free;
  end;

  MessageBox( 0, 'Test', '', 0 );
  CloseHandle( hEndEvent );
end.


И код оконного, где виснет:
var
  hEndEvent: THandle;

type
  TMyThread = class( TThread )
  protected
    procedure Execute; override;
  end;

procedure TMyThread.Execute;
var
  v: Variant;
begin
  CoInitialize( nil );
  v := CreateOleObject( 'AddIn.FprnM45' ); // Здесь виснет
  SetEvent( hEndEvent );
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  hEndEvent := CreateEvent( nil, True, False, nil );

  with TMyThread.Create( False ) do begin
    WaitForSingleObject( hEndEvent, INFINITE );
    Free;
  end;

  MessageBox( 0, 'Test', '', 0 );
  CloseHandle( hEndEvent );
end;


В общем, я уже не знаю. Надо отдохнуть.
2 сен 15, 00:17    [18097791]     Ответить | Цитировать Сообщить модератору
 Re: OLE-объект в потоке  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 2404
_Vasilisk_,

Разница таки проявилась - консольное приложение или нет. В консольном работает, в оконном - нет.
2 сен 15, 00:21    [18097803]     Ответить | Цитировать Сообщить модератору
 Re: OLE-объект в потоке  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 9873
YuRock
В общем, я уже не знаю.
А так?
{$APPTYPE CONSOLE}
program Project1;
.................
begin
  PeekMessage(msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
  hEndEvent := CreateEvent( nil, True, False, nil );
  .................
end.
2 сен 15, 00:23    [18097809]     Ответить | Цитировать Сообщить модератору
 Re: OLE-объект в потоке  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 2404
_Vasilisk_,

Так тоже не виснет.
2 сен 15, 00:31    [18097836]     Ответить | Цитировать Сообщить модератору
 Re: OLE-объект в потоке  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 2404
_Vasilisk_
krapotkin
в принципе, что ему может помешать слазить "на минутку" в главный поток ((
Незнание, где именно главный поток?


Если объект перебирает потоки, и в каждом ищет окна (например, 1-е по creation order), и отправит этому окну сообщение (оно будет в главном потоке) - то в моем случае зависнет.
Другое дело, нафига такое надо.

Этот AxtiveX умеет показывать модальные окна. Я, конечно, их использовать не собирался. Но, может, он при создании как-то "подготавливает на будущее" их показ.
А в случае с консольным приложением - окон нет - вот и работает.
Жаль, так и есть.
2 сен 15, 00:35    [18097847]     Ответить | Цитировать Сообщить модератору
 Re: OLE-объект в потоке  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 2404
YuRock
Жаль, так и есть

= Жаль, если так и есть
2 сен 15, 00:36    [18097849]     Ответить | Цитировать Сообщить модератору
 Re: OLE-объект в потоке  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 9873
YuRock
Так тоже не виснет.
Плохо. Ну попробуйте еще, в первом приближении так
procedure TForm1.Button1Click(Sender: TObject);
var
  LRes: Cardinal;
begin
  hEndEvent := CreateEvent( nil, True, False, nil );

  with TMyThread.Create( False ) do begin
    repeat
      LRes := MsgWaitForMultipleObjects(2, @hEndEvent, False, INFINITE, QS_ALLEVENTS);
      case LRes of
        WAIT_FAILED: RaiseLastOSError;
        WAIT_OBJECT_0 + 1: begin
            while PeekMessage(msg, 0, 0, 0, PM_REMOVE) do begin
              TranslateMessage(msg); 
              DispatchMessage(msg); 
            end;
        end;
      end;
    until LRes = WAIT_OBJECT_0;
    Free;
  end;

  MessageBox( 0, 'Test', '', 0 );
  CloseHandle( hEndEvent );
end;
[/quote]
2 сен 15, 00:43    [18097865]     Ответить | Цитировать Сообщить модератору
 Re: OLE-объект в потоке  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 9873
Кажись, понял. Вот так
{$APPTYPE CONSOLE}
program Project1;

uses Windows, ComObj, Activex, Classes;

var
  hEndEvent: THandle;

type
  TMyThread = class( TThread )
  protected
    procedure Execute; override;
  end;

procedure TMyThread.Execute;
var
  v: Variant;
begin
  CoInitialize( nil );
  v := CreateOleObject( 'AddIn.FprnM45' ); // Здесь уже не виснет
  SetEvent( hEndEvent );
end;

begin
  CoInitialize( nil );
  hEndEvent := CreateEvent( nil, True, False, nil );

  with TMyThread.Create( False ) do begin
    WaitForSingleObject( hEndEvent, INFINITE );
    Free;
  end;

  MessageBox( 0, 'Test', '', 0 );
  CloseHandle( hEndEvent );
end.
должно повисать
2 сен 15, 01:01    [18097887]     Ответить | Цитировать Сообщить модератору
 Re: OLE-объект в потоке  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 2404
_Vasilisk_,

Да, так начало виснуть.
Более того, если закомментировать CoInitialize в доп. потоке потоке, то тоже виснет.
2 сен 15, 01:31    [18097911]     Ответить | Цитировать Сообщить модератору
 Re: OLE-объект в потоке  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 2404
_Vasilisk_,

И еще, интересно, что если в тестовом оконном приложении закомментировать CoInitialize в доп. потоке, то тоже просто виснет, а если в моем рабочем приложении - то происходит соотв. исключение "Не был произведен вызов CoInitialize".

В общем, это всё интересные эксперименты. Жаль, как сделать, чтобы заработало, пока не ясно :(
2 сен 15, 01:34    [18097914]     Ответить | Цитировать Сообщить модератору
 Re: OLE-объект в потоке  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 2404
_Vasilisk_,

С MsgWait те же проблемы. Да у меня вряд ли получилось бы использовать такое в основном приложении - там мне нельзя обрабатывать сообщения в это время.
2 сен 15, 01:41    [18097916]     Ответить | Цитировать Сообщить модератору
 Re: OLE-объект в потоке  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 2404
О!

Если в консольном в главном потоке написать
CoInitializeEx( nil, COINIT_MULTITHREADED );

а в доп. потоке не вызывать CoInitialize, то всё работает!
2 сен 15, 02:06    [18097920]     Ответить | Цитировать Сообщить модератору
 Re: OLE-объект в потоке  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 2404
Странные эксперименты продолжаются.

Если в тестовом оконном Project1 перед
Application.Initialize;

написать
CoInitFlags := COINIT_MULTITHREADED;


то делфя при инициализации, видимо, вызовет
CoInitializeEx( nil, COINIT_MULTITHREADED );

и тоже всё работает. Причем что с вызовом в доп. потоке CoInitialize, что без.

А вот в основном проекте нифига не помогло.
Если в доп. потоке не вызвать CoInitialize(Ex) - будет исключение "Не был произведен вызов CoInitialize", а если вызвать ( CoInitialize или CoInitializeEx( nil, COINIT_MULTITHREADED ) ) - будет зависание, как и раньше.
Блин, я просто разницы не вижу.
Поток очереди создан так же с параметрами по умолчанию через TThread, как и в тестовом Project1; основной поток ждет создания этого объекта в доп. потоке через такой же WaitForSingleObnject. Ну просто нет разницы, шо за фигня 1 сентября свалилась на голову.
2 сен 15, 02:27    [18097926]     Ответить | Цитировать Сообщить модератору
 Re: OLE-объект в потоке  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 9873
YuRock
Блин, я просто разницы не вижу.
Читать про apartment вызовы ком-объекта. Если вкратце, то все вызовы com-объектов, у которых потоковая модель apartment выполняются в одном потоке. Если вызов метода произошел в другом потоке, то вызов маршалится в apartment-поток процесса, там выполняется и результат возвращается в вызвавший поток. apartment поток в процессе ровно один. Тот, кто первый вызвал
CoInitializeEx( nil, COINIT_APARTMENTTHREADED);
Здесь немного детальнее
YuRock
С MsgWait те же проблемы
А если так еще попробовать
LRes := MsgWaitForMultipleObjectsEx(1, @hEndEvent, False, INFINITE, QS_ALLEVENTS, MWMO_ALERTABLE);
2 сен 15, 14:24    [18099987]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Delphi Ответить