我有一个delphi(Win32)Web应用程序,可以作为CGI应用程序,ISAPI或Apache DLL运行。我希望能够生成一个唯一的文件名前缀(在给定时刻对所有当前请求都是唯一的),并认为执行此操作的最佳方法是使用processID(处理CGI模式)以及threadID(处理dll模式)。
如何在Delphi中获得唯一的进程ID和线程ID?
这些在多核/多处理器情况下是否是唯一的(在单个网络服务器上)?
编辑:请注意我被建议不要使用此方法,因此接受的答案使用不同的方法生成临时文件名
答案 0 :(得分: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()。
答案 1 :(得分: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;
答案 2 :(得分:4)
答案 3 :(得分:3)
不保证进程ID在Windows上是唯一的。它们对于过程的生命当然是独一无二的,但是一旦过程消失,它的id就可以立即重用。我不确定ThreadIDs。如果这些是临时文件,你可以使用等同于tmpfile或tmpnam的东西(C函数,但我认为Delphi有一个等价的。)
正如Jamie发布的GUID可能更好。
答案 4 :(得分:3)
1)如何获得独特的Process ID&amp; Delphi中的ThreadID:
答案:
注意:确保在实现部分中的“使用”子句中添加“窗口”
注意:红衣主教是无符号32位整数,范围从0到4294967295
implementation
uses Windows;
procedure MySolution();
var
myThreadID:Cardinal;
myProcessID:Cardinal;
begin
myThreadID := windows.GetCurrentThreadID;
myProcessID := windows.GetCurrentProcessId;
end;
2)这些在多核/多处理器情况下(在单个网络服务器机器上)是否是唯一的? 答案:是的。
进程标识符有效 创建过程的时间直到 这个过程已经终止了 整个系统独一无二。 (不 处理器独有的)
直到线程终止, 线程标识符唯一标识 整个系统的线程。 (同样,系统范围,不是唯一的 处理器)
答案 5 :(得分:2)
优于其中任何一个选项,您应该使用系统函数_tempnam。它在目录中返回一个不存在的文件的随机文件名。如果您愿意,可以为_tempnam提供前缀,以便您创建的文件可以识别。如果您提供唯一的前缀,则不应担心有人打开您的文件。然而,还有另一种解决方案。
_tempnam只有在你想将文件放入任意目录时才有用。如果您不关心目录是系统临时目录,请改用tempfile_s。它还会为您创建文件,因此不必担心竞争条件......只有当您尝试打开比系统可以处理的更多临时文件时才会出现错误。 tempfile_s的一个重大缺点是,一旦你关闭它,文件就会消失。
编辑:我得到了一个downvote,因为这是一个C函数。您可以通过将它们导入delphi来访问C运行时。看一下msvcrt.dll here的一些例子。function _tempnam(const Dir: PChar, const Prefix: PChar): PChar; cdecl;
external 'msvcrt.dll' name '_tempnam';
答案 6 :(得分:1)
其他人都给了你一个好的和合理的想法,但仍然 - 如果你正在使用文件进行临时存储,并且如果这些文件将始终首先创建(如果有一个同名的剩余文件则无关紧要已经在磁盘上,因为你会覆盖它,然后processid_threadid方法是完全有效的。
使用GetCurrentProcessID和GetCurrentThreadID Win32调用来访问这两个ID。