【问题标题】:Can I create a unique filename based on ProcessID and ThreadID?我可以根据 ProcessID 和 ThreadID 创建一个唯一的文件名吗?
【发布时间】:2010-09-21 07:53:21
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: multithreading delphi cgi isapi


    【解决方案1】:

    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;
    

    【讨论】:

    • 我会选择这个。请注意,MSDN 文档说-“由于用于生成文件名的算法,GetTempFileName 在创建大量具有相同前缀的文件时表现不佳。在这样的情况下在这种情况下,建议您根据 GUID 构造唯一的文件名"
    【解决方案2】:

    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) 在多核/多处理器情况下(在单个网络服务器机器上)这些是唯一的吗?
    答案:是的。

    进程标识符从 进程创建的时间,直到 该进程已被终止并且是 在整个系统中独一无二。 (不是 处理器独有)

    直到线程终止, 线程标识符唯一标识 整个系统的线程。 (再次,系统范围,不是唯一的 处理器)

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

        您在这里提出了许多好主意。

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

        不;我相信我们依靠 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( )。

        【讨论】:

        • 我采用了这种方法,因为它被证明是最简单的,并且从临时文件放入系统临时文件夹的 POV 来看更“正确”。我认为我的进程+线程 ID 想法有效,但我还需要添加代码来说明创建多个文件的线程..
        【解决方案5】:

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

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

        编辑:我投了反对票,因为这是一个 C 函数。您可以通过将它们导入 delphi 来访问 C 运行时。看看 msvcrt.dll here 的一些示例。

        function _tempnam(const Dir: PChar, const Prefix: PChar): PChar; cdecl;
          external 'msvcrt.dll' name '_tempnam';
        

        【讨论】:

        • 它是否还会创建一个空文件来“锁定”名称? - 也就是说,如果在生成名称和创建文件之间存在瞬间延迟(如果我需要自己创建文件),是否有任何发生冲突的机会
        • 不确定这是否在默认情况下在 delphi 中可用。 GetTempFileName 的 MSDN 文档确实提到了使用 GUID
        【解决方案6】:

        你能不改用GUID吗?

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

        CreateGuid
        GuidToString
        

        【讨论】:

          【解决方案7】:

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

          由于 Jamie 发布的 GUID 可能会更好。

          【讨论】:

          • “在给定时刻对所有当前请求都是唯一的” - 重用进程 ID 就可以了,因为文件只会在请求的生命周期内存在。然而,我想确定的是,在多核系统上,它们在特定时刻是独一无二的。并且添加线程 ID 将解释多线程
          • 这意味着文件是临时的(至少看起来是这样),在这种情况下,我将只使用 tmpfile 或其 Delphic 等效文件。
          猜你喜欢
          • 1970-01-01
          • 2011-04-25
          • 1970-01-01
          • 2013-08-13
          • 2020-11-14
          • 1970-01-01
          • 2014-08-26
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多