![]() |
Thread aufrufen, 1x laufen lassen, fertig
Ich habe ein kleines Problem mit Threads. Die Situation ist die: Ich rufe eine Prozedur auf, die im Prinzip das Programm blockieren würde. Sie macht ihre Arbeit, kehrt dann zurück, und dann geht´s weiter. Bei Fenstern passiert dann dieses unschöne "weiß werden", und im TaskMan steht u.U. "reagiert nicht", usw.
Das habe ich bei der alten Delphi-Version mit einem Thread gelöst:
Delphi-Quellcode:
aufgerufen sah das dann so aus:
//
// merging // var fThreadIsBusy : boolean = false; function ThreadProc(p: pointer): integer; stdcall; var session : HxSession; col : IHxCollection; s : string; begin Result := 0; // get namespace name s := string(p); if(s = '') then exit; // set busy flag fThreadIsBusy := true; // create "HxSession" interface if(CoInitializeEx(nil,COINIT_APARTMENTTHREADED or COINIT_SPEED_OVER_MEMORY) = S_OK) then try session := CoHxSession.Create; if(session <> nil) then begin // initialize namespace try session.Initialize(widestring('ms-help://' + s),0); except session := nil; end; if(session <> nil) then begin // Get "IHxCollection" interface, ... col := session.Collection; // ... & merge index if(col <> nil) then col.MergeIndex; end; session := nil; end; finally CoUninitialize; end; // clear busy flag fThreadIsBusy := false; end; procedure MergeNamespace(const NamespaceName: string; ThreadPriority: TPrioritySet = tpHighest); const RealPriorityClasses : array[TPrioritySet]of integer = (THREAD_PRIORITY_ABOVE_NORMAL, THREAD_PRIORITY_BELOW_NORMAL, THREAD_PRIORITY_HIGHEST, THREAD_PRIORITY_IDLE, THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_TIME_CRITICAL); var dwThreadId : dword; hThread : THandle; begin if(NamespaceName = '') then exit; // set busy flag fThreadIsBusy := true; // create thread, ... hThread := CreateThread(nil,0,@ThreadProc, pointer(NamespaceName),0,dwThreadId); if(hThread <> 0) then begin // ... & set its priority SetThreadPriority(hThread,RealPriorityClasses[ThreadPriority]); CloseHandle(hThread); end; end; function MergeIsBusy: boolean; begin Result := fThreadIsBusy; end;
Delphi-Quellcode:
So wurde der Dialog mit der Statusmeldung immer aktualisiert, usw.
MergeNamespace('MS.PSDK.1033');
while(MergeIsBusy) do ProcessMessages(dlg); In CSharp habe ich das jetzt so versucht:
Code:
Prinzipiell klappt es auch, :stupid:, nur der Thread wird nicht ordnungsgemäß freigegeben/entfernt, so dass ein zweiter Aufruf nicht mehr funktioniert. Und in meinem Tool kann man diesen Merging-Prozess auch mehrmals aufrufen, wenn man will. Bei Delphi habe ich "CloseHandle" benutzt, aber bei CSharp?
public sealed class MergeNamespace
{ #region ConsoleMerge public static void CallConsoleMerge(string namespaceName) { try { HxSession session = new HxSession(); session.Initialize(String.Format("ms-help://{0}", namespaceName), 0); IHxCollection collection = session.Collection; collection.MergeIndex(); } catch { } } #endregion #region UiMerge private static bool threadIsBusy = false; private static string nspaceName = String.Empty; private static Thread mergeThread = null; public static bool ThreadIsBusy { get { return threadIsBusy; } } private static void ThreadProc() { CallConsoleMerge(nspaceName); threadIsBusy = false; try { mergeThread.Join(); } catch { } } public static void CallUiMerge(string namespaceName) { if(namespaceName == null || namespaceName == "") return; threadIsBusy = true; nspaceName = namespaceName; mergeThread = new Thread(new ThreadStart(ThreadProc)); mergeThread.Start(); } #endregion public MergeNamespace() { } } Hat jemand einen Tipp für mich? Bessere Ideen sind natürlich auch willkommen. Wichtig ist mir, wie gesagt, dass ich mit folgender Konstruktion:
Code:
den Dialog regelmäßig aktualisieren kann, so dass der User nicht den Eindruck hat, das Programm hat sich aufgehangen, denn dieses Merging kann manchmal doch recht lange dauern.
MergeNamespace.CallUiMerge("MS.PSDK.1033");
while(MergeNamespace.ThreadIsBusy) { Application.DoEvents(); }; |
Re: Thread aufrufen, 1x laufen lassen, fertig
Gibts für C# keine DAU TThread-Klasse?
|
Re: Thread aufrufen, 1x laufen lassen, fertig
Falls du unter DAU das verstehst, was ich denke :stupid:, dann ist die Thread-Klasse schon so was. Das Problem ist für mich nur, dass der Thread nur beim ersten Mal korrekt funktioniert. Beim zweiten Mal sehe ich kurz den Dialog aufblinken (der eigentlich die Statusmeldung zeigen soll), und -schwupps- ... fort ist er wieder. Ich vermute daher, der Thread wird nicht korrekt beendet oder "zerstört".
Bei der Delphi-Version habe ich das mit "CloseHandle" erledigt (s. Codeausriss), und das klappt dann jedes Mal. Selbst wenn ich die Funktion quasi mehrmals aufrufe. |
Re: Thread aufrufen, 1x laufen lassen, fertig
*** Wo bleibt mein Push-Button *** :mrgreen: |
Re: Thread aufrufen, 1x laufen lassen, fertig
Zitat:
Sage mal, du startest den zwar, aber er wird ja nirgends mehr freigegeben. Passiert das automatisch, oder gibt's in der Klasse vielleicht auch ne Property, die du auf True setzen mußt, damit das Threadobjekt sich nach Ablauf selber killt (wie bei TThread in Delphi). |
Re: Thread aufrufen, 1x laufen lassen, fertig
Zitat:
|
Re: Thread aufrufen, 1x laufen lassen, fertig
Ja, der Code funktioniert bei mir.
Edit-PS: Genau so eine Möglichkeit suche ich ja, @Olli. Bisher sind mir nur "Join()" und "Abort()" ins Auge gefallen. Eine Möglichkeit zum direkten Zerstören scheint es nicht zu geben. :gruebel: Und die Thread-Klasse ist auch nicht von IDisposable abgeleitet, so dass ich ![]() |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:00 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz