2010-11-30 35 views
4

J'utilise ce code dans un thread (via l'événement Indy Onexecute). y a-t-il un problème ?Y at-il un problème à utiliser ce code dans un thread? (Delphi)

function TFrmMain.ShellExecute_AndWait(FileName, Params: string): bool; 
var 
    exInfo: TShellExecuteInfo; 
    Ph: DWORD; 
begin 
    FillChar(exInfo, SizeOf(exInfo), 0); 
    with exInfo do 
    begin 
    cbSize := SizeOf(exInfo); 
    fMask := SEE_MASK_NOCLOSEPROCESS or SEE_MASK_FLAG_DDEWAIT; 
    Wnd := GetActiveWindow(); 
    exInfo.lpVerb := 'open'; 
    exInfo.lpParameters := PChar(Params); 
    lpFile := PChar(FileName); 
    nShow := SW_NORMAL; 
    end; 
    if ShellExecuteEx(@exInfo) then 
    Ph := exInfo.hProcess 
    else 
    begin 
    Result := true; 
    exit; 
    end; 
    while WaitForSingleObject(exInfo.hProcess, 50) <> WAIT_OBJECT_0 do 
    begin 

    end; 
    CloseHandle(Ph); 
    Result := true; 
end; 

Répondre

8

MSDN a ce conseil:

Parce que ShellExecuteEx peut déléguer l'exécution à des extensions Shell (sources de données, les gestionnaires de menu contextuel, les implémentations de verbe) qui sont activés à l'aide Object Model COM (Component), COM devrait être initialisé avant l'appel de ShellExecuteEx. Certaines extensions Shell requièrent le type COM single-threaded apartment (STA). Dans ce cas, COM doit être initialisé comme indiqué ici:

CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE) 

Il y a des cas où ShellExecuteEx n'utilise pas un de ces types d'extension Shell et les cas ne nécessitant COM à initialiser du tout. Néanmoins, il est recommandé de toujours initialiser COM avant d'utiliser cette fonction.

(Dans Delphi, vous auriez bien sûr remplacer le premier paramètre avec nil et utiliser or pour l'opération au niveau du bit.)

Raymond Chen a écrit récemment au sujet de the consequences of getting this wrong. L'exemple spécifique était que la fonction pouvait échouer avec le code d'erreur Error_Access_Denied.

C'est le seul problème potentiel de multithreading que je vois dans votre code. Voici d'autres choses qui me sont venues à l'esprit lorsque j'ai lu votre code, bien qu'elles n'aient rien à voir avec le multithreading (et pas même avec Indy).


Vous avez une manière particulière d'attendre l'arrêt du programme. Vous attendez plusieurs fois 50 millisecondes à la fois, mais si le processus n'est pas encore terminé, vous ne faites rien d'autre que d'attendre à nouveau. Décrivez plus précisément votre intention en spécifiant Infinite pour le délai d'expiration.


La fonction renvoie toujours True. S'il n'y a pas de valeur de retour utile, alors vous devriez juste en faire une procédure donc il n'y a pas de valeur de retour du tout. Ne confondez pas l'appelant avec des informations inutiles. Si vous souhaitez le conserver en tant que fonction, utilisez le type natif Delphi Boolean au lieu du type de compatibilité Windows Bool pour le type de retour. Je suis un peu inquiet à propos de l'idée d'un serveur exécutant des programmes interactifs pour l'utilisateur lors de la réception de messages réseau.


Notez que lorsque MSDN indique que vous ne pouvez pas obtenir un handle de processus. Il y a des cas où ShellExecuteEx peut traiter votre demande sans créer un nouveau processus, ainsi vous n'aurez rien à attendre.

L'utilisateur peut finir par utiliser le programme, et votre serveur sera bloqué en attente pendant tout ce temps. Je me demande s'il faut vraiment attendre du tout. Le client attendra-t-il une réponse du serveur?

+0

+1 mais vous devriez faire le nitpicking dans un commentaire

+0

Merci beaucoup Mr Kennedy – Kermia