Autor Beitrag
Bergmann89
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1742
Erhaltene Danke: 72

Win7 x64, Ubuntu 11.10
Delphi 7 Personal, Lazarus/FPC 2.2.4, C, C++, C# (Visual Studio 2010), PHP, Java (Netbeans, Eclipse)
BeitragVerfasst: Di 29.03.11 17:23 
Hey,

ich steh mal wieder vor nem Problem mit Threads (wie so oft in letzter Zeit). Ich hab ne Art ThreadPool (ist selbst ein Thread), der ein OLEExcelObject anlegt. In diesem Objekt legen die Workthreads dann ihre Daten ab. Wenn ich die Tabelle dann speichern will (im Context des ThreadPools) kommt folgende Meldung: EOleSysError: 'Eine Schnittstelle, die für einen anderen Thread marshalled war, wurde von der Anwendung aufgerufen.'
Mit der Meldung kann ich aber nich wirklich was anfangen. Hier mal noch ein Auzug aus dem Code zum Excel-Objekt:
ausblenden volle Höhe 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:
60:
61:
62:
63:
64:
65:
66:
67:
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//schreibt die Daten eines Tippplans in die Excel-Datei
//@TPData: Daten des Tippplans;
//@Caption: Beschreibung/Überschirft des Tippplans;
//@SheetName: Name des Sheets, in das geschrieben werden soll;
//@TipCharCount: Zeiger auf die Verteilung der einzellnen Tippzeichen;
//@result: Errorcode;
function TExcelFile.WriteTipPlanData(TPData: TTipPlanData; Caption, SheetName: String; TipCharCount: PTipCharCount): Cardinal;
var
  Sheet: Variant;
  p: PSheetData;
  Col, Row, i, j: Integer;
  WaitResult: Cardinal;
  Arr: TArray3b;
begin
  WaitResult := WaitForSingleObject(fWriteTipPlanDataSem, SEMAPHORE_WAIT_TIME);
  try
    case WaitResult of
      WAIT_OBJECT_0: begin
        {mit Excelobject arbeiten und Daten ablegen...}
      WAIT_TIMEOUT: begin
        result := EXCEL_FILE_WAIT_FOR_SEM_TIMEOUT;
      end;
    else
      result := EXCEL_FILE_WAIT_FOR_SEM_ERROR;
    end;
  finally
    if not ReleaseSemaphore(fWriteTipPlanDataSem, 1nilthen
      result := EXCEL_FILE_RELEASE_SEM_ERROR;
  end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//speichert die Exceldatei
//@Filename: Datei in der gespeichert werden soll;
procedure TExcelFile.Save(Filename: String);
begin
  fWorkbook.SaveAs(Filename);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//erzeugt das Objekt
constructor TExcelFile.Create(ReqTipChars: TTipPlan; GameCount: Byte);
begin
  inherited Create;

  fWriteTipPlanDataSem := CreateSemaphore(nil11'');
  {...}
  CoInitializeEx(nil, COINIT_MULTITHREADED);
  fExcel := CreateOleObject('Excel.Application');
  fExcel.Application.SheetsInNewWorkBook := 1;
  fExcel.Workbooks.Add;
  fWorkbook := fExcel.Workbooks[1];
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//gibt das Objekt frei
destructor TExcelFile.Destroy;
var
  i: Integer;
begin
  for i := 1 to fExcel.Workbooks.Count do
    fExcel.Workbooks[i].Close(False);
  fExcel.Quit;
  {...}
  inherited Destroy;
end;

Weiß da jmd was ich falsch gemacht hab und kann mir da weiterhelfen?

MfG & Thx Bergmann.

_________________
Ich weiß nicht viel, lern aber dafür umso schneller^^
Chemiker
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 194
Erhaltene Danke: 14

XP, Vista 32 Bit, Vista 64 Bit, Win 7 64 Bit, Win 10, Win 11
BDS 2006, RAD Studio 2009+C++, Delphi 13, VS 2010 Prof.
BeitragVerfasst: Mi 30.03.11 00:45 
Hallo Bergmann89,

ob der Fehler im Thread liegt kann ich an Hand des Quelltextes nicht sagen. Aufgefallen ist mir allerdings das eine Verbindung zu einem Worbook nicht ordnungsgemäß getrennt wird.

Mit dieser Quellcodezeile wird der Variable fWorkbook ein Workbook zugewiesen.

ausblenden Delphi-Quelltext
1:
fWorkbook:= fExcel.Workbooks[1];					

aber in Destroy nicht wieder freigeben. Die Verbindung wird auch nach einem Close weiter aufrecht erhalten. Wenn jetzt die Verbindung zu Excel beendet wird bleibt die Verbindung weiter bestehen. (Kannst Du überprüfen wenn Du den Taskmanager aufrufst)
Um die Verbindung zu schließen bittet sich an das wie folgt zu realisieren:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
if (NOT VarIsEmpty(fWorkbook)) then
  begin
    fWorkbook.Close;
    fWorkbook:= Unassigned;
  end;
anschließend dann mit:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
if  NOT VarIsEmpty(fExcel) then
begin
  fExcel.Quit;
  fExcel:= Unassigned;
end;
Excel zu schließen.


Bis bald Chemiker
Bergmann89 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1742
Erhaltene Danke: 72

Win7 x64, Ubuntu 11.10
Delphi 7 Personal, Lazarus/FPC 2.2.4, C, C++, C# (Visual Studio 2010), PHP, Java (Netbeans, Eclipse)
BeitragVerfasst: Mi 30.03.11 09:21 
Hey,

danke für den Tipp, aber das hab ich im destructor alles drin stehen und Excel wird auch richtig beendet (kein Prozess mehr im Taskmanager). Den Test auf VarIsEmpty werd ich noch einfügen, den hab ich vergessen. Der Feler tritt ja beim Speichern auf, nicht beim schließen...

MfG Bergmann.

_________________
Ich weiß nicht viel, lern aber dafür umso schneller^^