1

嗨,我正在使用MSDN上描述的 SocketAsyncEventArgsPool 。

对于每个 TCP 客户端,我有一个自己的 50 个 SocketAsyncEventArgs 池(堆栈),可以从服务器写入客户端。所以,这工作正常,但是在重新启动客户端或服务器时,我有一个函数向客户端发送许多消息,并且对于每条消息,从我的池中获取一个 SocketAsyncEventArgs。当消息太多时,我的池为空并且没有可用的 SocketAsyncEventArgs 对象用于发送,并且此消息不会发送到客户端。

有没有可能在不增加我的池子的情况下避免这种情况???谢谢!!!

4

2 回答 2

1

如果池为空,只需创建一个新对象。这应该是一个罕见的事件。性能不应受到影响。

您还可以通过在不再使用新创建的对象时将其添加回池来动态增加池大小。这样,池大小会不断增加,直到满足所有需求。

于 2014-06-13T13:24:16.253 回答
0

如果您不想增加池的大小并假设您SocketAsyncEventArgs在使用后正确返回每个池,则可以使用BlockingCollection来保存所需数量的SocketAsyncEventArgs. 当没有更多的项目可以消费时,消费者将阻塞,直到一个项目返回到集合中。

更新

这是一些创建BlockingCollection大小为 1 的示例代码并触发一些消费者同时处理。每个消费者从集合中取出一个项目来处理它,同时其他消费者被阻止,Take直到一个项目被添加回集合中。

处理时,您可能需要在一个try/finally块中执行此操作,以确保在处理项目后,如果抛出异常,则始终将其添加回来。

要关闭您调用的集合CompleteAdding(),任何阻塞Take的方法都会抛出一个InvalidOperationException

public void RunConsumer(BlockingCollection<SocketAsyncEventArgs> collection, int consumerId)
{
    Task.Run( async () =>
    {
        Console.WriteLine("Consumer {0} waiting", consumerId);

        SocketAsyncEventArgs args = null;
        try
        {
            args = collection.Take();
            Console.WriteLine("Consumer {0} processing", consumerId);
            await Task.Delay(5000);
        }
        catch(ObjectDisposedException)
        {
           Console.WriteLine("Consumer {0} collection has been disposed", consumerId);
        }
        catch(InvalidOperationException)
        {
           Console.WriteLine("Consumer {0} collection has been closed", consumerId);
        }
        finally
        {
            // add the item back if collection hasn't been closed.
            if(args != null && !collection.IsAddingCompleted)
                collection.Add(args);
        }

        Console.WriteLine("Consumer {0} finished", consumerId);
    });
}

用法

void Main()
{
    var collection = new BlockingCollection<SocketAsyncEventArgs>(1) { new SocketAsyncEventArgs() };

    RunConsumer(collection, 1);
    RunConsumer(collection, 2);
    RunConsumer(collection, 3);

    Thread.Sleep(9000);
    collection.CompleteAdding();
    Console.ReadLine();
}

输出

Consumer 1 waiting
Consumer 3 waiting
Consumer 2 waiting
Consumer 1 processing
Consumer 1 finished
Consumer 3 processing
Consumer 2 collection has been closed
Consumer 2 finished
Consumer 3 finished
于 2014-06-13T07:29:55.727 回答