Einzelnen Beitrag anzeigen

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