Programm hinterlässt Prozess, obwohl beendet
-
Hallo,
@ Braunstein: Es wäre schön, wenn Du mir die Dateien schicken würdest.
Ich habe noch ein paar Tests gemacht und folgendes festgestellt:
1. Wenn ich die Eigenschaft Saved des geöffneten Excel-Workbooks auf false setze und somit beim Beenden von Excel der Abfragedialog zur Datenspeicherung erscheint und ich diesen Dialog mit JA bzw. NEIN verlasse, wird der Prozess ordnungsgemäß beendet.
2. Wenn ich die Eigenschaft Saved des geöffneten Excel-Workbooks auf true setze und somit Excel ohne Abfragedialog zur Datenspeicherung beendet wird bleibt der Prozess erhalten.
Ich hatte wohl noch nicht erwähnt, das die ganze Aktion in einem eigenen Thread abläuft und der Thread nach dem Schliessen von Excel beendet wird.
Ich hatte auch schon ein Sleep nach dem delete Excel eingebaut, das hat aber auch nichts gebracht.
Gruß Udo_11
-
Hallo,
Ich bin trotz mehrerer Versuche zu keinem Erfolg gekommen.
Ich denke, das ist ein Zeitproblem im Thread.Wenn ich nämlich die Excel-Instant außerhalb des Threads erstelle, dann wird diese beim Beenden des Threads immer beendet und auch der Prozess ist weg.
Das Problem ist nur, das ich dann im Thread nicht auf die Excel-Instanz zugreifen kann.void __fastcall Twk_satz::w_selectCompleted(TObject *Sender, bool &Cancel) { Cancel = dest_list->Items->Count < 2; if (!Cancel) { // ShowMessage("searched = "+BoolToStr(searched,true)); if (go_xls == NULL && !searched) { Excel = new TMLExcel; Excel->OpenWorkbook(MainForm->datapath+"excel\\s_u_test.xls"); Excel->CloseExcelOnTerminate = true; Application->ProcessMessages(); // Sleep(5000); go_xls = new XLSSearch(Excel->Books[0]); found1 = false; found2 = false; go_xls->OnTerminate = DeleteThread; } } else { . . . } } //---------------------------------------------------------------------------aus der .h-Datei des Threads:
class XLSSearch : public TThread { private: . . . TMLWorkbook *Excel; protected: void __fastcall Execute(); public: __fastcall XLSSearch(TMLWorkbook *Xls); };aus der .cpp-Datei des Threads:
__fastcall XLSSearch::XLSSearch(TMLWorkbook *Xls) : TThread(false) { Priority = tpNormal; FreeOnTerminate = true; } //---------------------------------------------------------------------------@Braunstein: Wenn Du mir die Dateien schicken willst --> udo.knirsch@stahlwerk-thueringen.de
Gruß Udo_11
-
Hallo,
Wieso kannst du im Thread nicht auf deine ExcelInstanz zugreifen? Du brauchst sie doch nur zu übergeben.
Um das Löschen der Excelinstanz sicher zu machen, würde ich hier die Verwendung eines Smartpointer empfehlen. Dann wird im Destruktor dein Excelprozess zuverlässig geschlossen. In deinem Fall empfehle ich boost::shared_ptr.
Die Dateien schicke ich dir gleich.Ciao
-
Hallo,
@Braunstein: Danke für die Mail, ist angekommen.
Ich habe mich im letzten Posting falsch ausgedrückt. Ich kann auf die Excel-Instanz zugreifen, aber der Zugriff scheint ins leere zu gehen. Jeder Versuch,
eine Eigenschaft zu verwenden, führt zu nichts. Die Funktionen werden nicht ausgeführt, es kommt keine Fehlermeldung, der Aufruf von GetLastError() liefert 0, der Thread wird beendet.Ich weiß echt keinen Rat mehr.
Gruß Udo_11
-
Ich würde deinen Thread etwas umorganisieren
class XLSSearch : public TThread { private: . . . TMLWorkbook *WorkBook; //Bezeichnung Excel ist etwas mißdeutlich protected: void __fastcall Execute(); public: __fastcall XLSSearch(TMLWorkbook *Xls); }; __fastcall XLSSearch::XLSSearch(TMLWorkbook *Xls) : TThread(false), WorkBook(Xls) // WorkBook sollte schon im Konstruktor initialisiert werden, woanders geht es ja nicht { Priority = tpNormal; FreeOnTerminate = true; }Hier muß natürlich sichergestellt werden, dass WorkBook immer auf eine gültige Instanz zeigt. Also Excel vorher nicht löschen.
-
Hallo,
@Braunstein: Habe Deinen Änderungsvorschlag eingearbeitet. Am Verhalten ändert sich jedoch nichts.
an einem Breakpoint im Debugger bekomme ich bei überwachten Ausdrücken folgende Ausgabe:
WorkBook: :01B2D2B0
WorkBook->WorksheetCount: E2122 Funktionsaufruf durch unbehandelte Exception 0xeedfade an Adresse 0x7c812a5b beendet
WorkBook->Sheets[0]->Name: E2122 Funktionsaufruf durch unbehandelte Exception 0xeedfade an Adresse 0x7c812a5b beendetDas bedeutet doch, das Workbook auf eine Speicheradresse zeigt, aber nicht verwendet werden kann ???
Gruß Udo_11
-
Nun, das Workbook muß natürlich existieren. Debugge mal von dem Punkt aus, wo das Workbook erzeugt wird.
-
Hallo,
Beim Debuggen ab dem Zeitpunkt der Erstellung der Excel-Instanz sieht das folgendermaßen aus:
Breakpoint Excel-Initialisierung --> Ok
Breakpoint im Konstruktor des Threads: WorkBook existiert (Adresse: 01B2D2B0) und ich kann in überwachten Ausdrücken alle Funktionen des WorkBook aufrufen.Breakpoint am Beginn der Execute-Methode des Threads: WorkBook-Adresse ist die gleiche, aber beim Zugriff auf die Funktionen des WorkBooks kommen die im letzten Posting gezeigten Fehler.
Gruß Udo_11
-
Dann scheint das Workbook irgendwo dazwischen freigegeben worden zu sein. Schau dir mal alle Funktionen an, mit denen man das Workbook freigebn kann. Setze gegebenenfalls Breakpoints in die Destruktoren von TMLWorkBook sowie TMLExcel und schau ob und wann die aufgerufen werden.
-
Hallo,
@Braunstein: Nach Deinem Hinweis von gestern habe habe ich den Debugger nochmal bemüht und folgendes festgestellt:
Im Konstruktor des Threads ist ein Zugriff auf WorkBook->Name möglich
Die Excel-Instanz wird bei mir nur in der Funktion gelöscht, welche ich dem OnTerminate-Ereignis des Threads zugewiesen habe.
OnTerminate wird laut Builder-Hilfe ausgelöst, wenn die Execute-Methode des Threads zurückkehrt.
Die Execute-Methode meines Threads wird beendet, weil sie einen Fehler beim Zugriff auf WorkBook->Name produziert.
-
Ok, ich ahne was los ist. Übergib mal statt der Workbookinstanz die Excelinstanz an deinen Thread. Die Excelinstanz verwaltet ja die Workbooks und da kann es evtl. vorkommen, dass der Pointer auf ein Workbook intern gelöscht und neu erzeugt wird. Dann hättest du einen ungültigen Pointer in deinem Thread.
-
Hallo,
Bei der Übergabe der Excel-Instanz an den Thread zeigt sich das gleiche Fehlerbild.
Der Fehler wird ausgelöst in der TMLExcel-Klasse in der Funktion GetWorkbookCount()
int TMLExcel::GetWorkbookCount() { if(!Connect) return 0; else return var_Excel.OlePropertyGet("Workbooks").OlePropertyGet("Count"); //in dieser Zeile !!! }Gruß Udo_11
-
Hallo,
Ich habe jetzt folgende Fehlermeldung:
Fehler:
Eine Schnittstelle, die für einen anderen Thread marshalled war, wurde von der Anwendung aufgerufenDas ganze hat mit Marshalling und COM+ zu tun. Ich habe auch schon etliche Artikel im Netz gefunden, weiß aber nicht so recht wie man das im konkreten Fall umsetzen muß.
Wenn dazu jemand etwas sagen kann, wäre das wunderbar.Gruß Udo_11
-
Hallo,
für alle, die es vielleicht interessiert. Ich habe jetzt eine Variante gefunden, bei welcher das Durchsuchen einer Exceldatei in einem eigenen Thread funktioniert.
Das Excel-Objekt wird im Thread initialisiert.
void __fastcall XLSSearch::Execute() { OleCheck(CoInitialize(NULL)); try { FExcel = new TMLExcel; FExcel->OpenWorkbook(MainForm->datapath+FileName); FExcel->CloseExcelOnTerminate = true; FExcel->Books[0]->Saved = true; // damit beim Schließen von Excel kein Speichern-Dialog eingeblendet wird try { ExcelSuche([Parameter]); // hier werden auch Parameter übergeben } catch(Exception &e) { msg = "Fehler beim Start der ExcelSuche():"; Synchronize(WriteMsg); //Eintrag in eine log-Datei msg = e.Message; Synchronize(WriteMsg); //Eintrag in eine log-Datei } } __finally { delete FExcel; FExcel = NULL; CoUninitialize; } } //---------------------------------------------------------------------------Die Funktion, die dem OnTerminate des Threads zugewiesen ist:
void __fastcall XLSSearch::DeleteThread(TObject *Sender) { delete FExcel; FExcel = NULL; CoUninitialize; Flog->Add("Thread beendet."); } //---------------------------------------------------------------------------Sooft ich getestet habe, wurde Excel ordnungsgemäß geschlossen und auch der Prozess jedesmal beendet.