使用RxExtensions停止监听UDP套接字的正确方法

时间:2016-11-24 07:42:30

标签: c# udp system.reactive

我需要监听UDP套接字,10秒后或缓冲区中的100个项目应该调用一些逻辑。一般来说它工作正常,但我不知道如何正确停止监听套接字。

var ip = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1234);
var socket = new UdpClient(ip);

var cancellationTokenSource = new CancellationTokenSource();
var observable =
  Observable
  .FromAsync(socket.ReceiveAsync)
  .DoWhile(() => !cancellationTokenSource.IsCancellationRequested)
  .Buffer(TimeSpan.FromSeconds(10), 100);

var subscribtion = observable.Subscribe(o =>
{
  //logic
});

//simulate close method from another thread
Task.Factory.StartNew(() =>
{
  Task.Delay(TimeSpan.FromSeconds(12)).Wait();
  cancellationTokenSource.Cancel();
  socket.Close();
  subscribtion.Dispose();
});

当我模拟关闭套接字时,存在一种情况,当缓冲区中存在一些无法处理的数据时 - 是否有任何方法可以避免这种行为?

当我以500毫秒的延迟从另一个进程发送一些消息时,它将如下所示:

  1. 20条消息将收入
  2. 将调用某些逻辑 - 订户逻辑
  3. 4条消息将收入
  4. 将调用模拟关闭方法
  5. 当调用“close方法”时,我需要立即处理缓冲区中的所有数据并关闭应用程序,而不等待缓冲区超时。缓冲延迟时间由用户定义,所以我不想等待调用用户逻辑,因为它可能需要相当长的时间。

1 个答案:

答案 0 :(得分:1)

欢迎使用StackOverflow!

缓冲区方法的现有重载不支持时间,计数和门。但是有一个重载会在序列产生值时触发缓冲区关闭。因此,我们将简单地通过合并缓冲区关闭的所有条件的可观察量来创建序列。

看一下这个演示。

onTime将在指定的时间段后生成一个值。

onCount将在x个项目过后生成第一个值。

onClose会在订阅时立即生成一个值 - 但在我们决定之前,我们不会连接到它。

            var producer = Observable.Interval(TimeSpan.FromSeconds(0.2));
            var source = producer.Publish().RefCount();

            var onClose = Observable.Return(0L).Publish();
            var onTime = Observable.Timer(TimeSpan.FromSeconds(2));
            var onCount = source.Skip(10);

            var bufferClose = Observable.Merge(onClose, onTime, onCount);

        var subscription =
            source
            .Buffer(() => bufferClose)
            .Subscribe(list => Console.WriteLine(string.Join(",", list)));

            Console.WriteLine("Waiting for close");
            Console.ReadLine();

            onClose.Connect(); //signal
            subscription.Dispose();

            Console.WriteLine("Closed");

            Console.ReadLine();

这将产生一个基于计数或时间的输出,直到按下返回,当它立即关闭缓冲区中可用的内容时。