在多线程环境中使用 .Net UdpClient

Posted

技术标签:

【中文标题】在多线程环境中使用 .Net UdpClient【英文标题】:use .Net UdpClient in a multithreaded environment 【发布时间】:2013-01-29 21:45:36 【问题描述】:

我有一个服务于一些线程的类的实例(我们称之为 A),这个实例只通过 UdpClient 类发送 UDP 数据包。 它在其构造函数中初始化 UdpClient,仅用于发送数据包。

它看起来像:

public class A

private UdpClient m_Client;
public class A(string host, int port)

    m_Client = new UdpClient(host, port);


public void Send(string dataToSend)

 var data= encoding.GetBytes(dataToSend);
 client.BeginSend(data, data.Length, null, null);



我的问题是:

我知道 UdpClient 不是线程安全的(根据 MSDN 文档),在不使用锁定机制的情况下支持多线程的最佳方法是什么?

    在每次发送时创建 UdpClient 的新实例? (只需使用一些本地 UdpClient 变量)。 性能?

    为 UdpClient 使用 ThreadLocal?但是在这种情况下如何处理 UdpClient 呢?

    还有其他解决方案吗?

【问题讨论】:

但是您不喜欢将锁定机制用于非线程安全的类? 出于性能考虑,我不想使用锁定机制... 锁定机制是解决此问题的最佳方法。您也可以自己编写锁定机制,但我认为它不会比微软提供的更快。您还写道,您可以为每个线程启动本地 UdpClient,它会起作用。但这不是正确的方法,您将通过锁定机制获得更多性能。启动新的 Udp 客户端需要太多时间,因此您应该尽量减少 UdpClient 启动的次数。实际上,我也有兴趣听取其他用户对这个问题的意见。 我没有看到 1) 有任何明显的性能问题。如果您按时处理它们,就不会有任何问题。 有趣的是,找不到UdpClient初始化的性能信息。如果它确实没有花费任何东西,那么 1) 是最好的解决方案,我相信。但我不确定性能... 【参考方案1】:

最终我相信我当前的实现应该没有问题(只要 Microsoft 不会更改 UdpClient 类的实现)。

可能对谁感兴趣: http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/cbdd9818-00f0-499f-a935-d8e555899d64

【讨论】:

【参考方案2】:

我认为这里最好的方法是在每次调用该方法时创建一个新的UdpClient。这样,您可以确保代码是安全的。性能不太可能是问题,如果性能分析显示问题是,那么您应该开始解决该问题。

此外,您不应忘记在每个 BeginSend() 之后调用 EndSend()(最好在回调中)。

【讨论】:

使用此特定代码示例的这种方法我看到的警告是,每次调用Send() 时,它都可能“从下面拉出地毯”一个已经在进行中的操作。这是因为客户端存储在类级别变量m_Client 中。作者需要确保创建客户端并将其存储在Send() 中的局部变量中,最好包裹在using 语句中。这可能会确保这个答案中的方法是安全的。

以上是关于在多线程环境中使用 .Net UdpClient的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Java 在多线程环境中测试某些东西 [重复]

在多线程环境中使用 PyCurl 时程序消耗的内存不断增长

可以在多线程环境中使用单个 QueueConnection 吗?

如何保护可能在多线程或异步环境中使用的资源?

在多线程环境中使用 std::string 时 Clang 的线程清理器警告

在多线程 Rails 环境中使用 Redis 的最佳方式是啥? (彪马/Sidekiq)