Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - EOleSysError bei Verwendung mit Thread


slain - Do 22.01.09 15:26
Titel: EOleSysError bei Verwendung mit Thread
Hallo, ich habe folgendes Problem:

Ich will in einem Webbrowser ein Feld füllen und möchte dies mit einem Thread tun.
Fülle ich das Feld ohne Thread, klappt es und mit Thread kommen folgende Fehlermeldungen, die ich in eine Textdatei gelogt habe:

22.01.2009 / 14:09:08:375: 12822= FillFormName 1 /
--------------------------------------- >>> EAccessViolation => Access violation at address 44C5B9B3 in module 'mshtml.dll'. Read of address 00000190
22.01.2009 / 14:09:08:375: 84959= FillFormName 1 /
--------------------------------------- >>> EOleSysError => Schwerwiegender Fehler
22.01.2009 / 14:09:08:375: 37402= FillFormName 1 /
--------------------------------------- >>> Das System kann die angegebene Datei nicht finden.
--------------------------------------- >>> EOleSysError => Schwerwiegender Fehler

Habt ihr eine Idee woran das liegen könnte?
Ich vermute, dass durch den Thread der Zugriff auf die Ole-Objekte bzw den Webbrowser irgendwie blockiert ist ...

Ich hoffe ihr habt eine Idee, die zur Problemlösung führt!


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
function TForm1.FillFormName(Versuche: integer; WebBrowser: TWebBrowser; FieldName: string; Value: string; Fundstelle:integer): Boolean;
var
  i, j, Fundstelle2: Integer;
  FormItem: Variant;
begin
try
  delay(10);
  result := false;
  application.ProcessMessages;
  Fundstelle2 := 0;
  if WebBrowser.OleObject.Document.all.tags('FORM').Length > 0 then
  for I := 0 to WebBrowser.OleObject.Document.forms.Length - 1 do
  begin application.ProcessMessages;
    FormItem := WebBrowser.OleObject.Document.forms.Item(I);
    for j := 0 to FormItem.Length - 1 do
    begin application.ProcessMessages;
      try
        if FormItem.Item(j).Name = FieldName then
        begin
          inc(Fundstelle2);
          if Fundstelle2 = Fundstelle then
          begin
            FormItem.Item(j).Value := Value;
            application.ProcessMessages;
            if FormItem.Item(j).Value = Value then
            begin
              Result := True;
              Exit;
            end
          end;
        end;
      except on E: Exception do
        Write_Msg(true, 'LOG', Exe_pfad, nil, ('FillFormName 1 / ' + GetLastErrorText(E)));
      end;
    end;
  end;
  if result = false then
  if Versuche > 0 then
  begin
    delay(100); // ein bisschen warten
    Write_Msg(true, 'LOG', Exe_pfad, nil, ('FillFormName Versuch NR: ' + IntToStr(Versuche)));
    FillFormName(Versuche-1 ,Webbrowser,Fieldname,Value,Fundstelle);
  end;
except on E: Exception do
  Write_Msg(true, 'LOG', Exe_pfad, nil, ('FillFormName 2 / ' + GetLastErrorText(E)));
end;
end;

procedure test;
begin
  Form1.FillFormName(1 ,Form1.Webbrowser_0, 'nick''test'1);
end;

procedure TForm1.Panel41Click(Sender: TObject);
var
  ThreadID : Cardinal;
begin
  createthread(0,0,@test,nil,0,ThreadID);
end;



Moderiert von user profile iconNarses: Topic aus Internet / Netzwerk verschoben am Do 22.01.2009 um 14:45


Narses - Do 22.01.09 15:44

Moin und :welcome: im Forum!

Wenn ich das richtig sehe, dann greifst du im Thread auf VCL-Komponenten zu. Das darfst du aber nicht unsynchronisiert tun (-> Synchronize() nehmen!)! :idea:

cu
Narses


slain - Do 22.01.09 18:09

Vielen Dank schonmal, habe das jetzt mit TThread + synchronize probiert, längere Operationen führen aber dort dennoch zum hängen der GUI(was bei BeginThread mit gleichen Operationen nicht der Fall ist)

Ich würde aber gerne auf TThread verzichten und mit BeginThread arbeiten (weil ich da schon das warten auf Threads usw fertig habe)

wenn TThread nicht zum einfrieren führen würde, würde ich das ja lieber nutzen ...

ich fand leider nichts brauchbares unter den suchwörtern: "synchronisation, beginthread" :(


TThread habe ich so getestet (funzt zwar, aber hakt):


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
procedure TNewThread.test;
begin
  //Download einer größeren Datei per idHTTP ...
end;

procedure TNewThread.Execute;
begin
  Synchronize(test);
end;

procedure TForm1.Panel41Click(Sender: TObject);
var
  NewThread: TNewThread;
begin
  NewThread := TNewThread.Create(true);
  NewThread.FreeOnTerminate:= true;
  NewThread.Execute;


Narses - Do 22.01.09 18:27

Moin!

user profile iconslain hat folgendes geschrieben Zum zitierten Posting springen:
TThread habe ich so getestet (funzt zwar, aber hakt):
Das ist natürlich sinnlos, die Execute-Methode komplett zu synchronisieren, dann kannst du den Thread auch gleich weglassen. ;) Du musst nur die Zugriffe auf VCL-Komponenten synchronisieren. :idea:

cu
Narses