3

我有一个可以作为 CGI 应用、ISAPI 或 Apache DLL 运行的 delphi (Win32) Web 应用程序。我希望能够生成一个唯一的文件名前缀(在给定时刻对所有当前请求都是唯一的),并认为最好的方法是使用 processID(处理 CGI 模式)以及 threadID(处理dll 模式)。

如何在 Delphi 中获得唯一的进程 ID 和线程 ID?

这些在多核/多处理器情况下(在单个网络服务器机器上)是否是独一无二的?

编辑:请注意,我被建议不要使用这种方法,因此接受的答案使用不同的方法来生成临时文件名

4

7 回答 7

5

你在这里提出了很多好主意。

它是否还会创建一个空文件来“锁定”名称?

不; 我相信我们依靠 Windows 来确保自启动以来在同一台计算机上永远不会两次给出相同的临时文件名。

如果在生成名称和创建文件之间存在瞬间延迟(如果我需要自己创建文件),是否有可能发生冲突

不; 那将是一件非常糟糕的事情。

这是我一直用来获取临时文件的例程。

function GetTemporaryFileName:string;
var
  Path, FileName: array[0..MAX_PATH] of Char;
begin
  Win32Check(GetTempPath(MAX_PATH, Path) <> 0);
  Win32Check(GetTempFileName(Path, '~EX', 0, FileName) <> 0);
  Result:=String(Filename);
end;

您可以改用 JCL 中 JclFileUtils.pas 中的 FileGetTempName()。

于 2008-11-07T17:46:31.240 回答
5

Windows 提供了创建有保证的唯一文件名的功能。无需创建自己的:

这是围绕该功能的 Delphi 包装器:

function CreateTempFileName(aPrefix: string): string;
var
  Buf: array[0..MAX_PATH] of Char;
  Temp: array[0..MAX_PATH] of Char;
begin
  GetTempPath(MAX_PATH, Buf);
  if GetTempFilename(Buf, PChar(aPrefix), 0, Temp) = 0 then
  begin
    raise Exception.CreateFmt(sWin32Error, [GetLastError, SysErrorMessage(GetLastError)]);
  end;
  Result := string(Temp);
end;
于 2008-11-08T04:29:38.337 回答
4

您不能改用GUID吗?

编辑:应该第一次说,检查以下两个功能

CreateGuid
GuidToString
于 2008-11-07T17:13:11.697 回答
3

不保证进程 ID 在 Windows 上是唯一的。它们在进程的生命周期中肯定是唯一的,但是一旦进程终止,它的 id 可以立即重用。我不确定 ThreadID。如果这些是临时文件,您可以使用与 tmpfile 或 tmpnam 等效的东西(C 函数,但我假设 Delphi 有一个等效的)。

正如 Jamie 发布的那样,GUID 可能会更好。

于 2008-11-07T17:15:19.277 回答
3

1)如何在Delphi中获取唯一的Process ID & ThreadID:

答案:
注意:确保在实现部分的使用子句中添加“windows”
注意:基数是无符号的 32 位整数,范围从 0 到 4294967295

implementation
uses Windows;

procedure MySolution();
var
  myThreadID:Cardinal;  
  myProcessID:Cardinal;
begin
  myThreadID := windows.GetCurrentThreadID;
  myProcessID := windows.GetCurrentProcessId;
end;

2)这些在多核/多处理器情况下(在单个网络服务器机器上)是否是独一无二的?
回答:是的。

进程标识符从进程创建到进程终止有效,并且在整个系统中是唯一的。(并非处理器独有)

在线程终止之前,线程标识符在整个系统中唯一标识线程。(同样,系统范围,不是处理器独有的)

于 2008-11-08T03:47:48.767 回答
2

比这些选项中的任何一个都好,您应该使用系统函数_tempnam。它为不存在的文件返回目录中的随机文件名。如果您愿意,您可以为 _tempnam 提供前缀,以便您创建的文件可以识别为您的。如果您提供唯一的前缀,则不必担心有人打开您的文件。然而,还有另一种解决方案。

_tempnam 仅在您想将文件放入任意目录时才有用。如果您不关心该目录是系统临时目录,请改用tempfile_s。它还将为您创建文件,因此无需担心竞争条件...只有在您尝试打开的临时文件超出系统处理能力时才会发生错误。tempfile_s 最大的缺点是文件一旦关闭就会消失。

编辑:我被否决了,因为这是一个 C 函数。您可以通过将它们导入 delphi 来访问 C 运行时。在这里查看一些带有 msvcrt.dll 的示例。

function _tempnam(const Dir: PChar, const Prefix: PChar): PChar; cdecl;
  external 'msvcrt.dll' name '_tempnam';
于 2008-11-07T17:19:30.360 回答
1

其他人都给了您一个很好且合理的想法,但是仍然-如果您将文件用于临时存储并且总是首先创建这些文件(如果已经存在同名的剩余文件并不重要)磁盘,因为无论如何你都会覆盖它)然后 processid_threadid 方法是完全有效的。

使用GetCurrentProcessIDGetCurrentThreadID Win32 调用来访问这两个 ID。

于 2008-11-07T17:40:14.733 回答