Возможно ли и / или целесообразно использовать несколько каналов System.Threading.Channel в одном объекте? - PullRequest
0 голосов
/ 11 ноября 2019

Я работаю над веб-приложением .net core 3.0 и решил использовать System.Threading.Channels в одноэлементном сервисе. Верхний уровень моих служб запросов с областью действия внедряет этот синглтон для доступа к его каналам.

Я решил использовать этот шаблон для отделения запросов (которые производят прямые обновления для других подключенных клиентов) от выполнения этих обновлений.

Реализация ОДНОГО канала в объекте имеет много примеров.

Может кто-нибудь сказать мне, возможно ли / желательно ли использовать несколько каналов в моем синглтоне?

У меня пока нет проблем с созданием нескольких каналов и их "запуском" при создании синглтона. Мне просто не дошло до того, что я могу протестировать запросы нескольких клиентов на разных каналах синглтона, чтобы проверить, хорошо ли это работает. (Или вообще? ...)

Моя основная мотивация использования нескольких каналов - я хочу, чтобы синглтон делал разные вещи в зависимости от типа элемента в канале.

public class MyChannelSingleton 
{
    public Channel<MyType> TypeOneChannel = Channel.CreateUnbounded<MyType>();
    public Channel<MyOtherType> TypeTwoChannel = Channel.CreateUnbounded<MyOtherType>();

    public MyChannelSingleton() 
    {
        StartChannels();
    }

    private void StartChannels() 
    {
        // discarded async tasks due to calling in ctor
        _ = StartTypeOneChannel();
        _ = StartTypeTwoChannel();
    }

    private async Task StartTypeOneChannel()
    {
        var reader = TypeOneChannel.Reader;

        while (await reader.WaitToReadAsync())
        {
            if (reader.TryRead(out MyType item))
            {
                // item is sucessfully read from channel
            }
        }
    }

    private async Task StartTypeTwoChannel()
    {
        var reader = TypeTwoChannel.Reader;

        while (await reader.WaitToReadAsync())
        {
            if (reader.TryRead(out MyOtherType item))
            {
                // item is sucessfully read from channel
            }
        }
    }
}

Я также ожидаю, что никогда не "завершу" каналы и не предоставлю их в течение всего срока действия приложения.

1 Ответ

0 голосов
/ 11 ноября 2019

К сожалению, я не могу не найти исходный код . И вызов Документация разреженная будет преуменьшением. Так что я могу в лучшем случае сказать вам «если бы это был мой класс, как бы я это сделал».

Большая проблема с наличием нескольких каналов в памяти - особенно неограниченных - будет фрагментация памяти, вызывающая раннее OOM. В самом деле, даже с одним неограниченным, большой проблемой было бы увеличение коллекции. List<T> - это чуть больше, чем обертка вокруг T[] с некоторой поддержкой автоматического роста. Другая проблема с неограниченными списками состоит в том, что рано или поздно у вас закончатся индексы .

Как бы я решил эту проблему? A Связанный список . Примерно в 90% всех случаев Связанный список был бы последним набором, который я бы даже рассмотрел. Остальные 10% представляют собой конструкции типа Queues и Queue. И каналы очень очень похожи на очередь. Из этих 10% случаев в 9% я бы просто использовал то, что делает реализация Queue. Это оставшийся 1%.

Для произвольного доступа Связанный список является наихудшей возможной коллекцией. Для очередей это выполнимо. Но как избежать OOM, связанных с фрагментацией в .NET? Для минимизации затрат на рост? Для того, чтобы обойти предел жесткого массива? Там связанный список абсолютно непобедим .

А если он этого не делает? Можно создать собственную версию канала, которая делает , и просто заменит ее.

...