AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Thread aufrufen, 1x laufen lassen, fertig

Ein Thema von MathiasSimmack · begonnen am 20. Jun 2005 · letzter Beitrag vom 1. Jul 2005
Antwort Antwort
MathiasSimmack
(Gast)

n/a Beiträge
 
#1

Thread aufrufen, 1x laufen lassen, fertig

  Alt 20. Jun 2005, 18:32
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:
//
// 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;
aufgerufen sah das dann so aus:
Delphi-Quellcode:
MergeNamespace('MS.PSDK.1033');
while(MergeIsBusy) do ProcessMessages(dlg);
So wurde der Dialog mit der Statusmeldung immer aktualisiert, usw.

In CSharp habe ich das jetzt so versucht:


Code:
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()
   {
   }
}
Prinzipiell klappt es auch, , 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?

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:
MergeNamespace.CallUiMerge("MS.PSDK.1033");
while(MergeNamespace.ThreadIsBusy) { Application.DoEvents(); };
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.
  Mit Zitat antworten Zitat
alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#2

Re: Thread aufrufen, 1x laufen lassen, fertig

  Alt 20. Jun 2005, 20:57
Gibts für C# keine DAU TThread-Klasse?
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat
MathiasSimmack
(Gast)

n/a Beiträge
 
#3

Re: Thread aufrufen, 1x laufen lassen, fertig

  Alt 21. Jun 2005, 19:06
Falls du unter DAU das verstehst, was ich denke , 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.
  Mit Zitat antworten Zitat
MathiasSimmack
(Gast)

n/a Beiträge
 
#4

Re: Thread aufrufen, 1x laufen lassen, fertig

  Alt 1. Jul 2005, 20:58
*** Wo bleibt mein Push-Button ***
  Mit Zitat antworten Zitat
Olli
(Gast)

n/a Beiträge
 
#5

Re: Thread aufrufen, 1x laufen lassen, fertig

  Alt 1. Jul 2005, 21:15
Zitat von MathiasSimmack:
*** Wo bleibt mein Push-Button ***
... nimm doch leddls Nase.

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).
  Mit Zitat antworten Zitat
Benutzerbild von MagicAndre1981
MagicAndre1981

Registriert seit: 4. Jun 2004
Ort: Nordhausen
2.214 Beiträge
 
Delphi 7 Enterprise
 
#6

Re: Thread aufrufen, 1x laufen lassen, fertig

  Alt 1. Jul 2005, 21:45
Zitat von MathiasSimmack:

In CSharp habe ich das jetzt so versucht:

Code:
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()
   {
   }
}
Prinzipiell klappt es auch, , nur der Thread wird nicht ordnungsgemäß freigegeben/entfernt, so dass ein zweiter Aufruf nicht mehr funktioniert.
Echt der Code funktioniert bei dir? Ich bekomme schon beim Ersten Aufruf nach ein paar Sekunden die Fehlermeldung "COMException 0x800403BD".
André
  Mit Zitat antworten Zitat
MathiasSimmack
(Gast)

n/a Beiträge
 
#7

Re: Thread aufrufen, 1x laufen lassen, fertig

  Alt 1. Jul 2005, 22:20
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. Und die Thread-Klasse ist auch nicht von IDisposable abgeleitet, so dass ich Delphi-Referenz durchsuchenusing benutzen und so das Zerstören "erzwingen" könnte.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:26 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz