Есть ли проблемы с использованием этого кода в потоке? (Delphi) - PullRequest
4 голосов
/ 30 ноября 2010

Я использую этот код в потоке (через событие Indy Onexecute).есть ли проблема?

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;

1 Ответ

8 голосов
/ 30 ноября 2010

MSDN имеет этот совет:

Поскольку ShellExecuteEx может делегировать выполнение расширениям Shell (источникам данных, обработчикам контекстного меню, реализациям глаголов), которые активируются с помощью объектной модели компонентов (COM), COM следует инициализировать перед вызовом ShellExecuteEx. Для некоторых расширений Shell требуется тип однопоточной квартиры (STA) COM. В этом случае COM должен быть инициализирован, как показано здесь:

CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE)

В некоторых случаях ShellExecuteEx не использует один из этих типов расширения Shell, и эти экземпляры вообще не требуют инициализации COM. Тем не менее, перед использованием этой функции рекомендуется всегда инициализировать COM.

(В Delphi вы, конечно, заменили бы первый параметр на nil и использовали бы or для побитовой операции.)

Раймонд Чен недавно написал о последствиях неправильного понимания . Конкретным примером было то, что функция могла завершиться с ошибкой Error_Access_Denied.

Это единственная потенциальная проблема многопоточности, которую я вижу в вашем коде. Ниже приведены дальнейшие вещи, которые произошли со мной, когда я прочитал ваш код, хотя они не имеют ничего общего с многопоточностью (и даже не имеют ничего общего с Indy).


У вас есть особый способ ожидания остановки программы. Вы несколько раз ждете 50 миллисекунд за раз, но если процесс еще не завершен, вы ничего не делаете, только снова ждете. Опишите свое намерение более точно, указав Infinite для времени ожидания.


Функция всегда возвращает True. Если нет полезного возвращаемого значения, тогда вы должны просто сделать его процедурой, чтобы вообще не было возвращаемого значения. Не путайте звонящего с бесполезной информацией. Если вы собираетесь сохранить его как функцию, используйте тип возвращаемого значения Delphi Boolean вместо типа совместимости Windows Bool для возвращаемого типа.


Я немного настороженно отношусь к идее сервера, выполняющего пользовательские интерактивные программы при получении сетевых сообщений.


Обратите внимание, когда MSDN говорит, что вы можете не получить дескриптор процесса. Бывают случаи, когда ShellExecuteEx может обслуживать ваш запрос, не создавая новый процесс, поэтому вам нечего ждать.

Пользователь может в конечном итоге использовать программу некоторое время, и ваш сервер будет зависать все это время. Интересно, нужно ли вообще ждать? Будет ли клиент ожидать ответа от сервера?

...