【问题标题】:Same machine, different app domains, same GUIDs coming up相同的机器,不同的应用程序域,相同的 GUID 即将出现
【发布时间】:2017-12-20 12:58:14
【问题描述】:

我很确定我要么做错了什么,要么理解错了。很难给出一段代码来显示我的问题,所以我将尝试解释我的场景,以及结果。

我在同一个控制台应用程序中启动了几个 DLL 实例,但在它自己的应用程序域中。然后,我生成了一个 Guid.NewGuid(),我将它分配给实例中的一个类,并将应用程序的文件夹设置为一个新文件夹。到目前为止,这很好用。我可以看到一切都很好,我的实例是分开的。但是......当我开始将我的应用程序的文件夹更改为与为该类生成的唯一 GUID 相同的名称时,我开始选择异常。

当我缓慢地实例化新实例时,它工作正常,但是当我敲入新实例时,应用程序在启动时开始在其文件夹中获取数据。经过一番调查,我发现这是因为该文件夹已经存在,因为该 GUID 已经被实例化。在进一步调查中,我可以看到机器暂停了一下,然后继续生成新实例,所有实例都具有相同的 GUID。

我知道 GUID 生成算法使用 MAC 作为其中的一部分,但我的印象是,即使同一台机器在同一时间生成两个 GUID,它仍然是唯一的。

我的说法正确吗?我哪里错了?

代码:

Guid guid = Guid.NewGuid();
string myFolder = Path.Combine(baseFolder, guid.ToString());
AppDomain ad = AppDomain.CurrentDomain;
Console.WriteLine($"{ad.Id} - {guid.ToString()}");

string newHiveDll = Path.Combine(myFolder, "HiveDriveLibrary.dll");
if (!Directory.Exists(myFolder))
{
    Directory.CreateDirectory(myFolder);
}
if (!File.Exists(newHiveDll))
{
    File.Copy(hiveDll, newHiveDll);
}
Directory.SetCurrentDirectory(myFolder);

var client = ServiceHelper.CreateServiceClient(serviceURL);

ElementConfig config = new ElementConfig();
ElementConfig fromFile = ElementConfigManager.GetElementConfig();
if (fromFile == null)
{
    config.ElementGUID = guid;
    config.LocalServiceURL = serviceURL;
    config.RegisterURL = registerServiceURL;
}
else
{
    config = fromFile;
}

【问题讨论】:

  • 您确定它正在生成相同的 Guid 吗?并不是说您的代码只是重新使用相同的 Guid?您将不得不发布可以复制问题的最短代码量
  • Guid.NewGuid 不使用 MAC(这是在 ~2000 年默认的 GUID 生成),但它应该避免冲突。我认为这是另一种形式的“污染”,您认为孤立的东西实际上是共享的,这使得 外观它是 GUID 冲突。
  • 一点点阅读和快速谷歌搜索确实表明这是一个潜在的问题。似乎时间是种子的一部分,所以如果它们是在同一时刻创建的,所有其他细节都相同,那么就有重复的机会。但是找不到任何避免它的答案。
  • 当前目录是一个每个进程的概念。那是你无意中的分享
  • " Not GUID related at all.."...我们从不怀疑

标签: c# guid appdomain


【解决方案1】:

Directory.SetCurrentDirectory 是 Kernel 32 函数 SetCurrentDirectory 之上的一个瘦包装器。

不幸的是,.NET documentation writers 没有选择从native function 复制警告:

多线程应用程序和共享库代码不应使用 SetCurrentDirectory 函数,并且应避免使用相对路径名。 SetCurrentDirectory 函数写入的当前目录状态作为全局变量存储在每个进程中,因此多线程应用程序无法可靠地使用该值,而不会从其他线程可能也正在读取或设置该值的数据损坏

正是您对该函数的依赖造成了多个线程神奇地选择了完全相同的 GUID 值的外观。

【讨论】:

  • 正确。您没有看到的是我加载了一个包含 GUID 的配置文件(从当前目录)。当它不存在时,它会创建一个新的 GUID,并将其放入配置中。然后另一个 AppDomain(现在也在“其他”文件夹中)选择该配置,并且不将 GUID 设置为实际的新 GUID。
猜你喜欢
  • 1970-01-01
  • 2019-05-09
  • 1970-01-01
  • 2021-10-06
  • 1970-01-01
  • 2013-10-31
  • 1970-01-01
  • 2015-11-29
  • 1970-01-01
相关资源
最近更新 更多