5

I have an instance of a class (lets call it A) which serves some threads, this instance only sends UDP packets via the UdpClient class. It initialize the the UdpClient in its constructor and only serves to send the packets.

It looks something like:

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);
}

}

My questions is:

I know that UdpClient isn't thread-safe (according to MSDN documentation), what is the best way to support multithreaded without using locking mechanism?

  1. On each send create new instance of the UdpClient? (just use some local UdpClient var). performance?

  2. Use ThreadLocal for the UdpClient? but what about the disposing of the UdpClient in this situation?

  3. Any other solution?

svick
  • 236,525
  • 50
  • 385
  • 514
Tomer Peled
  • 3,571
  • 5
  • 35
  • 57
  • But you dont like locking mechanism to use it for not thread-safe classes? – Maris Feb 14 '13 at 07:02
  • I don't want to use locking mechanism from performance concerns... – Tomer Peled Feb 14 '13 at 07:05
  • locking mechanism is best way to get right fix for this isue. Also you can write locking mechanism by your self, but I dont think that it will work faster than presented by microsoft. Also you wrote that you can initiate local UdpClient for each thread, it will works. BUT it's not right way, you will get more performance with the locking-mechanism. Initiating new Udp client takes too much time, so you should minimize count of UdpClient initiation. Actualy i'm also interested to listen to other user opinions for this question. – Maris Feb 14 '13 at 07:12
  • I don't see any obvious performance issue with 1). If you dispose them on time, there won't be any problem. – Lex Li Feb 14 '13 at 07:34
  • It's interesting, I can't find information on the performance of the initialization of the UdpClient. If it is indeed not costing anything than 1) is the best solution, I believe. But I'm not sure about the performance... – Tomer Peled Feb 14 '13 at 08:10
  • I've created some test which creates the UdpClient each time , execute the begin send and then Dispose the UdpClient (I don't need any callback handling) and there was performance degradation in the execution. I also found that the UdpClient eventually uses the Socket class which is thread-safe and it seems that the BeginSend only use the BeginSend of the Socket class - http://reflector.webtropy.com/default.aspx/DotNET/DotNET/8@0/untmp/whidbey/REDBITS/ndp/fx/src/Net/System/Net/Sockets/UDPClient@cs/1/UDPClient@cs so it seems that if I use the current implementation it should work fine. – Tomer Peled Feb 14 '13 at 14:48

2 Answers2

1

Eventually I believe that my current implementation should work with no issues (as long as Microsoft won't change the UdpClient class implementation).

For whom it might be interesting: http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/cbdd9818-00f0-499f-a935-d8e555899d64

Tomer Peled
  • 3,571
  • 5
  • 35
  • 57
0

I think the best way here would be to create a new UdpClient every time the method is called. This way, you can be sure the code is safe. The performance isn't likely to be a problem, and if profiling shows that it is, only then you should start solving that.

Also, you shouldn't forget to call EndSend() after each BeginSend() (ideally in the callback).

svick
  • 236,525
  • 50
  • 385
  • 514
  • The caveat I see with this approach using this particular code sample is that each time `Send()` gets called, it could "pull the rug out from under" an operation that's already in process. This is because the client is stored in a class-level variable, `m_Client`. The author would need to make sure the client is created and stored in a local variable in `Send()`, preferably wrapped in a `using` statement. That would probably ensure that the approach in this answer would be safe. – bcr Oct 25 '21 at 20:01