Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 
 

78 rader
2.7 KiB

  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Threading.Tasks;
  4. using MQTTnet.Packets;
  5. namespace MQTTnet.Client
  6. {
  7. public class MqttPacketDispatcher
  8. {
  9. private readonly ConcurrentDictionary<Tuple<ushort, Type>, TaskCompletionSource<MqttBasePacket>> _awaiters = new ConcurrentDictionary<Tuple<ushort, Type>, TaskCompletionSource<MqttBasePacket>>();
  10. public void Dispatch(Exception exception)
  11. {
  12. foreach (var awaiter in _awaiters)
  13. {
  14. Task.Run(() => awaiter.Value.TrySetException(exception)); // Task.Run fixes a dead lock. Without this the client only receives one message.
  15. }
  16. _awaiters.Clear();
  17. }
  18. public void Dispatch(MqttBasePacket packet)
  19. {
  20. if (packet == null) throw new ArgumentNullException(nameof(packet));
  21. ushort identifier = 0;
  22. if (packet is IMqttPacketWithIdentifier packetWithIdentifier && packetWithIdentifier.PacketIdentifier.HasValue)
  23. {
  24. identifier = packetWithIdentifier.PacketIdentifier.Value;
  25. }
  26. var type = packet.GetType();
  27. var key = new Tuple<ushort, Type>(identifier, type);
  28. if (_awaiters.TryRemove(key, out var awaiter))
  29. {
  30. Task.Run(() => awaiter.TrySetResult(packet)); // Task.Run fixes a dead lock. Without this the client only receives one message.
  31. return;
  32. }
  33. throw new InvalidOperationException($"Packet of type '{type.Name}' not handled or dispatched.");
  34. }
  35. public void Reset()
  36. {
  37. _awaiters.Clear();
  38. }
  39. public TaskCompletionSource<MqttBasePacket> AddPacketAwaiter<TResponsePacket>(ushort? identifier) where TResponsePacket : MqttBasePacket
  40. {
  41. var tcs = new TaskCompletionSource<MqttBasePacket>();
  42. if (!identifier.HasValue)
  43. {
  44. identifier = 0;
  45. }
  46. var key = new Tuple<ushort, Type>(identifier ?? 0, typeof(TResponsePacket));
  47. if (!_awaiters.TryAdd(key, tcs))
  48. {
  49. throw new InvalidOperationException($"The packet dispatcher already has an awaiter for packet of type '{key.Item2.Name}' with identifier {key.Item1}.");
  50. }
  51. return tcs;
  52. }
  53. public void RemovePacketAwaiter<TResponsePacket>(ushort? identifier) where TResponsePacket : MqttBasePacket
  54. {
  55. if (!identifier.HasValue)
  56. {
  57. identifier = 0;
  58. }
  59. var key = new Tuple<ushort, Type>(identifier ?? 0, typeof(TResponsePacket));
  60. _awaiters.TryRemove(key, out _);
  61. }
  62. }
  63. }