|
Вопрос # 5 072/ вопрос открыт / |
|
Здравствуйте!
у меня программа - сом сервер и клиент клиент проверяется значение переменной в бесконечном цикле и отображает её. цикл в отдельном потоке . выходит ошибка: приложение обратилось к интерфейсу относящемуся к другому потоку
 |
Вопрос задал: SoulOfAngel (статус: Посетитель)
Вопрос отправлен: 7 марта 2011, 17:52
Состояние вопроса: открыт, ответов: 1.
|
Ответ #1. Отвечает эксперт: Вадим К
Здравствуйте, SoulOfAngel!
Так как с Вашего треда происходит обращение к ActiveX компонентам, то Вы обязаны в этом треде инициализировать подсистему, отвечающую за ActiveX и Com. А в главном треде это происходит автоматически, если только используется хотя бы один компонент ActiveX. Смотрим пример тут http://chrisbensen.blogspot.com/2007/06/delphi-tips-and-tricks_26.html
 |
Ответ отправил: Вадим К (статус: Академик)
Время отправки: 7 марта 2011, 22:18
|
Мини-форум вопроса
Всего сообщений: 6; последнее сообщение — 9 марта 2011, 01:29; участников в обсуждении: 3.
|
Егор (статус: 10-ый класс), 7 марта 2011, 18:48 [#1]:
ошибка в 17-ой строке
Опасайтесь багов в приведенном выше коде; я только доказал корректность, но не запускал его.
— Donald E. Knuth.
|
|
SoulOfAngel (статус: Посетитель), 7 марта 2011, 19:12 [#2]:
основной поток
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComObj;
type
TForm1 = class(TForm)
Button1: TButton;
ColorDialog1: TColorDialog;
Label1: TLabel;
Label2: TLabel;
Button2: TButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
//Server:Variant;
public
{ Public declarations }
end;
var
Form1: TForm1;
status:boolean;
implementation
uses unit2;
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
var co:check;
begin
//Server:=CreateOLEObject('MyServer.AutoServer');
end;
procedure TForm1.FormDestroy(Sender: TObject);
var co:check;
begin
//Server:=NULL;
co.Terminate;
end;
procedure TForm1.Button1Click(Sender: TObject);
var co:check;
begin
status:=false;
co:=check.Create(true) ;
co.Resume;
co.Priority:=tpLower;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
status:=true;
end;
end.
в основном потоке цикл работает
вот 2-й поток:
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComObj, unit1, myserver_tlb, activex;
type
check = class(TThread)
private
{ Private declarations}
Server:Variant;
protected
procedure Execute; override;
procedure UpdateCaption;
//function check.CoInitializeEx (pvReserved : pointer; coInit : longint) : HResult; stdcall;
end;
implementation
{ Important: Methods and properties of objects in visual components can only be
used in a method called using Synchronize, for example,
Synchronize(UpdateCaption);
and UpdateCaption could look like,
procedure check.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end; }
{ check }
procedure check.Execute;
begin
CoInitializeEx (NIL, COINIT_APARTMENTTHREADED);
{ Place thread code here }
Server:=CreateOLEObject('MyServer.AutoServer');
while true do
begin
Synchronize(UpdateCaption);
sleep(300);
if status=true then //CoUninitialize(nil) and
exit;
end;
end;
procedure check.UpdateCaption;
begin
if Server.Color=0 then
form1.label2.caption:=('выкл') ;
if Server.Color=1 then
form1.label2.caption:=('вкл') ;
if Server.Color=2 then
form1.label2.caption:=('на половину взведён') ;
if terminated then exit;
end;
end.
<code>
|
|
SoulOfAngel (статус: Посетитель), 7 марта 2011, 20:05 [#3]:
Вроде бы надо сделать маршлинг. Помогите пожалуйста организовать маршлингв моём коде.
|
|
SoulOfAngel (статус: Посетитель), 7 марта 2011, 23:05 [#4]:
Здравствуйте Вадим, значит маршлинг мне не нужен?
|
|
Вадим К (статус: Академик), 8 марта 2011, 21:49 [#5]:
Я даже не представляю, как сюда втиснуть маршлинг.
Кстати, вот эта строка
if terminated then exit;
будучи вызванной с процедуры синхронизации потоков, может сделать совсем не то, что хочется. Я бы ее назад в execute перенес.
Присмотрелся ближе к коду, и нашел причину.
Дело в том, что когда вызывается какой то метод через Synchronize, то он отрабатывает в главном треде. А у Вас в этом методе есть обращение к полям ActiveX объекта. С учетом сказанного я бы его переписал как минимум так
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComObj, unit1, myserver_tlb, activex;
type
check = class(TThread)
private
{ Private declarations}
Server:Variant;
mycolor:integer;// я не совсем уверен, integer ли тут.
protected
procedure Execute; override;
procedure UpdateCaption;
end;
implementation
{ check }
procedure check.Execute;
begin
CoInitializeEx (NIL, COINIT_APARTMENTTHREADED);
{ Place thread code here }
Server:=CreateOLEObject('MyServer.AutoServer');
while (not status) and (not terminated) do begin
mycolor := Server.Color;
Synchronize(UpdateCaption);
sleep(300);
end;
end;
procedure check.UpdateCaption;
begin
case mycolor of
0: form1.label2.caption:= 'выкл';
1: form1.label2.caption:= 'вкл';
2: form1.label2.caption:= 'на половину взведён';
else
form1.label2.caption:='непонятный';
end;
end;
end.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
SoulOfAngel (статус: Посетитель), 9 марта 2011, 01:29 [#6]:
Спасибо вам Вадим я разобрался. Вы были правы. Если не трудно ответьте на вопрос может ли моя программа работать с другими серверами сом на пример написанными на VB?
|
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|