Delphi - TDictionary 线程安全吗

2024-03-01

我的想法是使用 TDictionary 来管理 IdTCPServer 上的客户端连接。这是一个用于理解目的的简单示例代码(未经测试):

var
  Dic: TDictionary<string, TIdContext>;

procedure TfrmMain.FormCreate(Sender: TObject);
begin
  Dic := TDictionary<string, TIdContext>.Create;
end;

procedure TfrmMain.FormDestroy(Sender: TObject);
begin
  Dic.Free;
end;

procedure TfrmMain.TCPServerConnect(AContext: TIdContext);
var
  Hostname: string;
begin
  Hostname := UpperCase(GStack.HostByAddress(AContext.Binding.PeerIP));
  if not Dic.ContainsKey(Hostname) then Dic.Add(Hostname, AContext);
end;

procedure TfrmMain.TCPServerDisconnect(AContext: TIdContext);
var
  Hostname: string;
begin
  Hostname := UpperCase(GStack.HostByAddress(AContext.Binding.PeerIP));
  if Dic.ContainsKey(Hostname) then
  begin
    Dic[Hostname].Free;
    Dic.Remove(Hostname);
  end;
end;

这段代码线程安全吗?


一句话:No.

如果您检查来源词典您应该很快意识到实现本身没有提供线程安全性。即使是这样,通过离散调用Dic例如,您有潜在的竞争条件需要应对:

  if Dic.ContainsKey(Hostname) then
  begin

    // In theory the Hostname key may be removed by another thread before you 
    //  get a chance to do this : ...

    Dic[Hostname].Free;
    Dic.Remove(Hostname);
  end;

你需要自己利用Dic线程安全,幸运的是,在这种示例中,可以使用对象本身的监视器轻松实现这一点:

MonitorEnter(Dic);
try
  if not Dic.ContainsKey(Hostname) then 
    Dic.Add(Hostname, AContext);

finally
  MonitorExit(Dic);
end;


// ....


MonitorEnter(Dic);
try
  if Dic.ContainsKey(Hostname) then
  begin
    Dic[Hostname].Free;
    Dic.Remove(Hostname);
  end;

finally
  MonitorExit(Dic);
end;

如果您不熟悉 Delphi 中的监视器,简单来说,您可以将监视器视为一个随时可用的临界区,受每个TObject后代(在旧版本的 Delphi 中,不支持这些监视器,您可以通过显式关键部分实现相同的目标)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Delphi - TDictionary 线程安全吗 的相关文章

  • 如何释放 TInterfacedObject 中的 TObject 成员

    我知道接口对象是引用计数的 因此不需要手动释放它 但如果它有一个 TObject 继承成员 我是否应该在析构函数中手动释放该成员 考虑以下代码 program Project2 APPTYPE CONSOLE R res uses Syst
  • 如何用不同的颜色绘制选定的列表框项目?

    是否可以更改 TListBox 中的项目选择焦点颜色和文本颜色 当项目中未启用主题或列表框样式设置为所有者绘制时 项目周围的选择将被涂成蓝色 我相信这是由系统的外观设置全局定义的 我想将所选项目的颜色更改为自定义颜色 举个例子 结果会是这样
  • 使用单独的线程在java中读取和写入文件

    我创建了两个线程并修改了 run 函数 以便一个线程读取一行 另一个线程将同一行写入新文件 这种情况会发生直到整个文件被复制为止 我遇到的问题是 即使我使用变量来控制线程一一执行 但线程的执行仍然不均匀 即一个线程执行多次 然后控制权转移
  • 当底层连接是有状态时如何使用 Apache HttpClient?

    我在谷歌上搜索了很多关于如何使用 HttpClient 进行多线程处理的信息 他们中的大多数人建议使用 ThreadSafeClientConnManager 但我的应用程序必须登录某个主机 登录表单页面 以便 HttpClient 获得底
  • 如何在Spring-Boot中创建DefaultMessageListenerContainer?

    我是 Spring Boot 的新手 并尝试创建 DefaultMessageListenerContainer 以便我可以使用 weblogic workmanager 并以多线程方式运行多个消息侦听器 有人可以提供一些例子吗 到目前为止
  • 打印 TDBGrid [重复]

    这个问题在这里已经有答案了 如何在不安装或下载组件的情况下打印 DBGrid OR 如何将 DBGrid 的数据放入 RichEdit 以便我可以从那里打印它 数据感知控件从 DataSource 属性获取数据 并使用它 不过 您必须手动遍
  • 异步回调在哪个线程上运行?

    我正在做几个HttpWebRequest BeginGetResponse调用 并在回调方法中BeginGetResponse 我正在调用一个事件处理程序 在EventHandler中 有测试下载是否成功的逻辑 如果没有 它会尝试重新下载
  • 防止多个实例 - 但还要处理命令行参数?

    我正在从我的应用程序处理与 Windows 相关的扩展文件 因此 当您在 Windows 中双击文件时 它将执行我的程序 然后我从那里处理该文件 如下所示 procedure TMainForm FormCreate Sender TObj
  • 当使用环回地址使用 TCP/IP 套接字进行 IPC 时,常见的网络堆栈是否会跳过将消息帧封装在较低级别的 PDU 中?

    在某些环境 例如 Java 中 很自然地使用 TCP IP 套接字通过 localhost 地址 IPv4 中的 127 0 0 1 或 IPv6 中的 1 在同一主机上的进程之间传递消息 因为Java倾向于不在其API中公开其他IPC机制
  • 通过套接字发送动态数组(在记录内)?

    我正在尝试直接使用 SendBuf 将记录从服务器传输到客户端 但是 该记录有一个动态数组的成员 并且我在某处 在 SOF 中 读到 发送记录时 成员必须是静态的 固定长度 但问题是 我无法确定如何我会 将来 发送许多论点 我怎么解决这个问
  • 如果其中一台机器死机,TCP 连接如何终止?

    如果两个主机 A 和 B 之间建立了 TCP 连接 假设主机 A 已向主机 B 发送了 5 个八位字节 然后主机 B 崩溃了 由于未知原因 主机 A 将等待确认 但如果没有收到确认 将重新发送八位字节并减小发送者窗口大小 这将重复几次 直到
  • 在不支持线程的程序加载的共享库中使用 C++11 多线程

    我目前正在尝试在共享库中使用 C 11 多线程 该库加载到 Linux 上的主程序 用 C 编写 中 这是一个大型模拟程序的一部分 我无法更改有关库加载的任何内容或更改一般的主程序 主程序是用 gcc 4 1 2 编译的 我没有它的源代码
  • 如何比较枚举类型集

    从某个时刻开始 我厌倦了编写设定条件 and or 因为对于更多的条件或更长的变量名 重新编写会变得笨拙且烦人 所以我开始写助手这样我就可以写ASet ContainsOne ceValue1 ceValue2 代替 ceValue1 in
  • 父子进程之间的通信

    我正在尝试创建一个具有一个或多个子进程的 Python 3 程序 父进程生成子进程 然后继续处理自己的业务 有时我想向特定的子进程发送一条消息 由其捕获该消息并采取行动 此外 子进程在等待消息时需要处于非锁定状态 它将运行自己的循环来维护服
  • Delphi - 如果没有创建类,为什么这个函数可以工作?

    考虑这个类 unit Unit2 interface type TTeste class private texto string public function soma a b integer string end implementa
  • Android:如何使用后台线程?

    我开发了一个应用程序 它从互联网获取内容并相应地在设备的屏幕上显示它 该程序运行得很好 就是有点慢 加载并显示内容大约需要 3 4 秒 我想将获取内容并将其显示在后台线程中的所有代码放在一起 当程序执行这些功能时 我想显示一个进度对话框 你
  • 中断 Select 以添加另一个要在 Python 中监视的套接字

    我正在 Windows XP 应用程序中使用 TCP 实现点对点 IPC 我正在使用select and socketPython 2 6 6 中的模块 我有三个 TCP 线程 一个读取线程通常会阻塞select 一个通常等待事件的写入线程
  • 在 C# 中创建加密随机数的最快、线程安全的方法?

    请注意 在多个线程上并行生成随机数时 加密随机数生成器不是线程安全的 使用的发电机是RNGCryptoServiceProvider它似乎重复了很长一段随机位 128 位 重现此情况的代码如下所示 缺乏使用锁来保护访问RNGCryptoSe
  • 如何在多线程C++ 17程序中交换两个指针?

    我有两个指针 pA 和 pB 它们指向两个大的哈希映射对象 当pB指向的哈希图完全更新后 我想交换pB和pA 在C 17中 如何快速且线程安全地交换它们 原子 我是 c 17 的新手 2个指针的原子无等待交换可以通过以下方式实现 inclu
  • 从其可执行文件的路径获取服务名称

    我有一个可执行文件的路径 它是一个正在运行的服务应用程序 例如 C Program Files x86 Someapp somesvc exe 我想停止并启动它 为此我想我需要获取服务的名称 如下所示 this https stackove

随机推荐

  • python + googledrive:上传xlsx,转换为googlesheet,获取可共享链接

    我想要的程序的流程是 上传 xlsx 电子表格到驱动器 它是使用 pandas 创建的to excel 将其转换为 Google 表格格式 指定任何知道该链接的人都可以对其进行编辑 获取链接并与将输入信息的人共享 下载完成的表格 我目前正在
  • JavaScript 保留关键字

    我想知道 JavaScript 的保留关键字 函数是如何管理的 Example 根据 http www quackit com javascript javascript reserved words cfm http www quacki
  • JSF2/PrimeFaces 中的命名容器 [重复]

    这个问题在这里已经有答案了 PrimeFaces 中可能的命名容器有哪些 当我们想要使用以下命令更新表单上的某些 UI 控件时 为什么需要为 Ajax 更新调用附加命名容器 idupdate mainForm MainAccordian u
  • Visual Studio Code 中的语言可以扩展吗?

    Scenario 我有 JSON 文件 描述了一系列要执行的任务 其中每个任务都可以引用 JSON 文件中的其他任务和对象 tasks id first action doSomething result id second action
  • 如何使用python解压文件

    我怎样才能提取一个 zip or rar使用 Python 文件 迟到了 但我对任何答案都不满意 pip install patool import patoolib patoolib extract archive foo bar rar
  • 我可以使用 URL 打开 Windows 8 应用程序吗?

    我正在创建一个具有共享会话功能的应用程序 例如 私人应用程序到应用程序的聊天会话 我会启动应用程序并创建一个 聊天室 然后通过电子邮件与某人 共享 我想要做的是创建一个 URL 当单击它时 它会打开您计算机上的应用程序 如果我邀请您到我的
  • 在 C# Windows 窗体应用程序中捕获 Ctrl + Shift + P 击键 [重复]

    这个问题在这里已经有答案了 可能的重复 在 Windows 窗体应用程序中捕获组合键事件 https stackoverflow com questions 3062587 I need to perform a particular op
  • Java使用索引来一一显示数组

    我在按索引显示数组时遇到问题 我不知道为什么会发生这种情况 任何帮助将不胜感激 这是我的代码片段 create token2 String token2 create Scanner inFile2 Scanner inFile2 new
  • Swift 3 - 调整字体大小以适合宽度、多行

    我有一个 UILabel 它设置为 42 0 pt 字体 并且标签的宽度是使用基于标签本身以外的因素的自动约束设置的 也就是标签右侧和左侧的内容决定标签的宽度 我想自动调整字体大小以适应标签的宽度 但也可以的话分成两行 与此类似 我知道您可
  • 如何将表达式插入到R中的函数体中

    我有一个函数f lt function x x 我想插入该行x lt 2 x into f这样它最终会变成 function x x lt 2 x x 我明白我应该使用body 但到目前为止我只知道如何替换entire身体 这对于我的真正目
  • 如何修复输入和参数张量不在同一设备上?

    我看到其他人也遇到此错误 我尝试按照步骤解决 但仍然收到此错误 运行时错误 输入和参数张量不在同一设备上 在 cpu 处找到输入张量 在 cuda 0 处找到参数张量 我运行 model to device 和 input seq to d
  • PDFKit - 使用 pageViewController 的 PDFView - 滑动到下一页时页面渲染缓慢

    我有一个设置为使用 pageViewController 的 PDFView let pdfView PDFView let pdfDoc PDFDocument url Bundle main url forResource test w
  • 将 Eclipse Android 项目更新到下一个版本

    我在 Eclipse 中有一个 android 项目 我开始在 android 版本 2 2 中开发 我认为 我想更新该项目以在我的 2 3 3 设备上运行 有没有办法升级项目或者我需要创建一个新项目 因此 根据您的问题 我只想说 Andr
  • 修复发送信号中断系统调用时的竞争条件

    我有一个线程read 来自套接字 我希望能够异步停止线程 线程伪代码如下所示 int needs quit 0 void thread read void arg while 1 if needs quit close sock fd re
  • AlbersEqualArea 使用 lon 和 lat 限制区域

    我的数据是 100o 30o lon 和 0o 80o lat 我想使用投影来仅显示该区域 在我的脑海中 我想展示这样的情节 但是 当我尝试 AlbersEqualArea 投影时 如下所示 plt figure figsize 5 129
  • 使用 OkHttp、Okio 和 RxJava 下载文件

    我正在尝试使用 OkHttp 下载文件并使用 Okio 写入磁盘 我还为此过程创建了一个 rx observable 它正在工作 但是它比我以前使用的 Koush 的 Ion 库 明显慢 以下是我创建可观察对象的方法 public Obse
  • 无法将“System._COMObject”类型的 COM 对象转换为接口类型

    我有 3 个 SSIS 包 3 个 SSIS 包中的两个可以完美运行 第三个 这是第二个的副本 除了更改连接字符串不断引发问题 无法将类型 System ComObject 的 COM 对象强制转换为接口类型 Microsoft SqlSe
  • 在 for 循环中未设置的批处理脚本变量无效

    下面是我的脚本 我试图查看下面一层的文件夹并仅挑选出这些文件夹 因此 9 从路径中提取最后 9 个字符 但 set var 不会取消设置变量 因为输出返回时 相同的文件夹名称重复 次 另外 批处理不允许我直接在 i 上执行此提取技巧 因此需
  • 存根和mockito中的区别

    我是mockito新手 需要知道存根和何时之间的区别 1 stub cpproxy getBinList toReturn gettestbins 2 when cpproxy getBinList thenReturn gettestbi
  • Delphi - TDictionary 线程安全吗

    我的想法是使用 TDictionary 来管理 IdTCPServer 上的客户端连接 这是一个用于理解目的的简单示例代码 未经测试 var Dic TDictionary