• Какую актуальную библиотеку можно использовать в роли брокера сообщений внутри .NET приложения?

    AlexanderYudakov
    @AlexanderYudakov
    C#, 1С, Android, TypeScript
    Решил размяться.

    Вот шина:
    MessageBus.cs

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Threading.Tasks;
    
    namespace SimpleMessageBus
    {
        /// <summary>
        /// Рассылает события заинтересованным подписчикам
        /// в рамках одного приложения.
        /// </summary>
        /// <remarks>Используются WeakReference, чтобы не было утечек памяти
        /// на случай, если кто-то забудет отписаться. Поэтому не рекомендуется
        /// использовать лямбда-обработчики событий.</remarks>
        public static class MessageBus
        {
            private static readonly Dictionary<string, List<WeakReference<Action<string, object>>>> Subscribers =
                new Dictionary<string, List<WeakReference<Action<string, object>>>>();
    
            /// <summary>
            /// Оформляет подписку на событие
            /// </summary>
            /// <param name="topic">Тип события</param>
            /// <param name="handler">Подписчик</param>
            public static void Subscribe(string topic,
                Action<string, object> handler)
            {
                if (String.IsNullOrEmpty(topic))
                    throw new ArgumentNullException(nameof(topic));
    
                if (handler == null)
                    throw new ArgumentNullException(nameof(handler));
    
                List<WeakReference<Action<string, object>>> handlers;
                lock (Subscribers)
                    if (!Subscribers.TryGetValue(topic, out handlers))
                        handlers = Subscribers[topic] = new List<WeakReference<Action<string, object>>>();
    
                lock (handlers)
                    handlers.Add(new WeakReference<Action<string, object>>(handler));
            }
    
            /// <summary>
            /// Отменяет подписку на событие
            /// </summary>
            /// <param name="topic">Тип события</param>
            /// <param name="handler">Подписчик</param>
            public static void Unsubscribe(string topic,
                Action<string, object> handler)
            {
                if (String.IsNullOrEmpty(topic))
                    throw new ArgumentNullException(nameof(topic));
    
                if (handler == null)
                    throw new ArgumentNullException(nameof(handler));
    
                List<WeakReference<Action<string, object>>> list;
                lock (Subscribers)
                    if (!Subscribers.TryGetValue(topic, out list))
                        return;
    
                lock (list)
                {
                    var i = 0;
                    while (i < list.Count)
                    {
                        var reference = list[i];
                        if (!reference.TryGetTarget(out var target))
                            list.RemoveAt(i); // Заодно очищаем список от мертвых подписчиков
                        else if (target == handler)
                        {
                            list.RemoveAt(i);
                            return;
                        }
                    }
                }
            }
    
            /// <summary>
            /// Оповещает подписчиков о наступлении события
            /// </summary>
            /// <param name="topic">Тип события</param>
            /// <param name="data">Данные события</param>
            public static void Publish(string topic, object data = null)
            {
                if (String.IsNullOrEmpty(topic))
                    throw new ArgumentNullException(nameof(topic));
    
                List<WeakReference<Action<string, object>>> list;
                lock (Subscribers)
                    if (!Subscribers.TryGetValue(topic, out list))
                        return;
    
                var handlers = new List<Action<string, object>>();
                lock (list)
                {
                    var i = 0;
                    while (i < list.Count)
                    {
                        var reference = list[i];
                        if (!reference.TryGetTarget(out var target))
                            list.RemoveAt(i);
                        else
                        {
                            handlers.Add(target);
                            ++i;
                        }
                    }
                }
    
                // В Unity вызывать обработчики событий, наверное,
                // нужно как-то так:
                UnityEngine.WSA.Application.InvokeOnAppThread(() =>
                // А в обычном консольном приложении так:
                // Task.Run(() =>
                {
                    foreach (var handler in handlers)
                    {
                        try
                        {
                            handler.Invoke(topic, data);
                        }
                        catch (Exception ex)
                        {
                            Debug.WriteLine(ex);
                        }
                    }
                }, false);
            }
        }
    }


    Вот пример использования:
    using System.Diagnostics;
    using System.Threading.Tasks;
    
    namespace SimpleMessageBus
    {
        public static class Program
        {
            public static async Task Main(string[] args)
            {
                Debug.WriteLine("Started.");
    
                MessageBus.Subscribe("Rain", RainHandler);
                MessageBus.Publish("Rain");
    
                await Task.Delay(100); // Ждем, пока событие поступит
                MessageBus.Unsubscribe("Rain", RainHandler);
                
                Debug.WriteLine("Finished.");
            }
    
            private static void RainHandler(string topic, object data)
            {
                Debug.WriteLine("Event: " + topic);
            }
        }
    }


    P.S. Бесплатно. Опенсорс.

    Upd. Добавил вызов UnityEngine.WSA.Application.InvokeOnAppThread() — все-таки у нас целевая платформа Unity.
    Ответ написан
    1 комментарий
  • Какую актуальную библиотеку можно использовать в роли брокера сообщений внутри .NET приложения?

    vabka
    @vabka Куратор тега C#
    Токсичный шарпист
    Посмотри на System.Threading.Channels и rxNET.
    И ещё посмотри на ECS, как альтернативный способ избавиться от жуткой лапши
    Ответ написан
    1 комментарий
  • Слетает активация OEM-Windows на ноуте

    @edogs
    > Кто-нибудь в курсе каким-образом можно решить этот вопрос в свою пользу?
    Пробуйте активировать по телефону. Тут кроме микрософта никто не поможет.

    > Возможны ли варианты что я действительно не имею прав на винду в данной ситуации?
    Да. Как вариант — человек купил ноут и «отказался» от предустановленного софта, наклейка могла сохраниться.
    Если там была enterprise — вполне возможно закупался для конторы, корпоративка честная и поэтому оем-ка с наклейки нелегальна.
    Еще вариант — ноубтук был битый и ему меняли корпус, наклейка досталась по наследству:)
    Ответ написан
    Комментировать
  • Учеба в Китае?

    ixSci
    @ixSci
    Вы считаете, что в Китае Вас научат лучше чем в родной стране?
    Ответ написан
    2 комментария
  • Стоит ли осваивать новую профессию

    @nzim
    Заняться нечем? Лучше устройтесь преподавателем, больше пользы будет
    Ответ написан
    Комментировать
  • Способ обхода ограничения возраста в PayPal?

    Amadeusck
    @Amadeusck
    Смело регайтесь, возраст они будут проверять, только если вы будете активно продавать товары или услуги. Если вы будете только покупать, то всем «нас рать» на вас, только бы деньги были чистые. Будут проблемы с документами, типа если потребуют документы в каком-то волшебном случае, то отпишите мне, я вам помогу решить вопрос в течении дня. Удачи.
    Ответ написан
    6 комментариев
  • Что делать с чатиком?

    nur
    @nur
    Поставить статус Не беспокоить
    Ответ написан
    1 комментарий
  • Есть ли возможность смотреть канал Discovery в интернете в хорошем качестве?

    pluser
    @pluser
    Я бы сделал и возможность есть но это как я понял не законно.
    Если кто знает как это сделать законно, подскажите.
    Ответ написан
    Комментировать
  • Автосигнализация не вскрываемая кодграббером?

    Ocelot
    @Ocelot
    1. Алгоритм требует двустороннего обмена данными. В простых сигналках (которые вскрываются граббером) поток данных однонаправленный: в брелоке передатчик, в базовом блоке — приемник.

    1.1 Если уж у нас есть двусторонний канал, что мешает применять нормальные криптографические протоколы аутентификации? Логика подсказывет, что в современных сигналках так и делается. Конкретные модели не назову, самому интересно. Производители почему-то тщательно скрывают информацию о своих протоколах.

    2. Запрашивать пароли нужно не по порядку, а рандомно (но следя, чтобы не было повторов). Иначе возможна следующая атака:
    — Жертва снимает машину с сигнализации. Брелок начинает сессию. Сигналка запрашивает пароль номер 100500. Брелок говорит пароль и команду. Запоминаем номер.
    — Жертва садится в машину и едет, следуем за ней.
    — Жертва ставит машину на сигнализацию. Брелок начинает сессию. Ставим помеху, база ничего не слышит.
    — Притворяемся базой и запрашиваем пароль номер 100501. Брелок говорит пароль и команду. Записываем.
    — Жертва видит, что ничего не произошло, и снова нажимает на кнопку. Брелок начинает сессию. Опять ставим помеху, база вновь ничего не слышит.
    — Притворяемся базой и запрашиваем пароль номер 100502. Брелок говорит пароль и команду. Записываем.
    — Притворяемся брелоком и начинаем сессию. База запрашивает пароль номер 100501. Говорим пароль и команду.
    — Машина становится на сигнализацию, жертва уходит.
    — Притворяемся брелоком и начинаем сессию. База запрашивает пароль номер 100502. Говорим пароль и команду. Машина наша.

    3. Брелок будет плохо защищен от копирования. Одно дело — хранить 128 бит ключа в защищенной памяти внутри криптопроцессора, а другое — сотни кБ-мегабайты одноразовых ключей. Потребуется внешняя флешка, которую можно легко прочитать.

    4. Что делать, когда ключи все-таки закончатся? Перепрошивать сигналку? Генерировать новые? А как их потом в брелок заливать? Нужно тщательно продумать этот момент.

    5. Как будет выглядеть процедура добавления в систему нового брелока?

    В целом идея хорошая и при грамотной реализации будет надежно работать. Но дьявол, как всегда, в деталях :)
    Ответ написан
    4 комментария
  • Черным по белому или белым по черному?

    @65520
    Попробуйте это. Ещё можно увеличить шрифты хотя бы в браузере. Я себе поставил 120% и мне стало гораздо комфортней.
    Ответ написан
    2 комментария
  • Выбор устройства для защиты ноутбука

    dudeonthehorse
    @dudeonthehorse
    Email Developer
    Стоит отойти от ноута, кот на него ложится. Попытаешься взять ноут или отогнать кота — будет орать так, что вор будет пойман с поличным.
    Ответ написан
    Комментировать
  • Как стать программистом?

    Stdit
    @Stdit
    Чтобы стать программистом, который не просто пишет по гайдлайнам, но ещё и всё понимает и чувствует код, надо написать не один десяток велосипедов и сравнить свои велосипеды с велосипедами других программистов. Понять, почему твой велосипед работает хуже и написать новый велосипед.

    К примеру, несколько моих знакомых, которых я считаю хорошими программистами, жаловались, что в детстве-юности самостоятельно изобрели волновой метод поиска кратчайшего пути, решето Эратосфена, и некоторые другие известные алгоритмы, разочаровавшись позже, что это уже давно известно.

    Конечно, я не одобряю велосипеды в профессиональном программировании, но для обучения и саморазвития, по-моему, нет ничего лучше.
    Ответ написан
    1 комментарий
  • Алгоритмы распознавания подписи?

    anmipo
    @anmipo
    Можно позаимствовать подход у распознавателей жестов (например, All-in-one Gestures).
    По мере рисования жеста (подписи), программа определяет направление движения мыши (стилуса), «округляя» его до одного из четырёх основных направлений: left, right, up, down. Повторение одного и того же направления игнорируется (то есть «LLLLL» считается одной «L») — это нивелирует разницу в масштабах жестов.

    В результате, даже такой сложный жест как подпись можно представить в виде сравнительно короткой последовательности а-ля ULDRUDRULDR (символ @ в моём исполнении), где каждый символ занимает всего два бита. Таким образом, десятка байт с лихвой хватит на хранение даже сложной подписи.

    Символ @ в направлениях

    Распознавание направления легко делается на лету: когда стилус сместился на N пикселей от начальной точки, сравниваем Δx c Δy, и их знаки; если полученное направление отличается от предыдущего — добавляем его в цепочку распознанных и goto 1. Мелкие дрожания руки можно отфильтровать, задав N > 1.

    Только прежде, чем реализовывать в железе, проверьте точность распознавания на компьютере, хоть в том же браузере. На всякий случай :)
    Ответ написан
    Комментировать
  • Какой монитор взять что бы меньше уставали глаза при работе?

    Killy
    @Killy
    Понижаю яркость и использую f.lux для управления цветовой температурой.
    Ответ написан
    1 комментарий
  • ASUS F3T - стоит ли ремонтировать?

    Mixailo
    @Mixailo Автор вопроса
    Спасибо всем за помощь, плюсанул всем где возможно.
    Видимо, буду покупать новый.
    Ответ написан
    Комментировать
  • ASUS F3T - стоит ли ремонтировать?

    theproof
    @theproof
    Никакой не шлейф.
    С большой вероятностью чип видяхи или северный мост.
    Смотрим типовые неисправности на серию Ф3 — notebook1.ru/forma1/viewtopic.php?f=338&t=22142

    Если есть проверенная хорошая ремонтная контора (или мастер), дающая гарантию, то можно ремонтировать.
    По ценам должно выйти 4-5 т.р.
    Хотя чипы такие новые наверное уже не купить (или сложно), поэтому тут может либо увеличиваться стоимость ремонта или уменьшаться время дальнейшей жизни ноутбука, т.к. поставят б\у чип.
    Ответ написан
    Комментировать
  • Вопрос диагоналей. Разрешение телевизора

    dude_sam
    @dude_sam
    BI Developer
    Не хочу разжечь холивора. Но в качестве ремарки отмечу.
    Panasonic очень хорош в высоком сегменте (мне он не по карману).
    Sony, скажем так, хорош во всех сегментах, но наценка за марку доходит до 30%, что тоже не очень выгодно для кармана.
    Я для себя (и для родственников и друзей) всегда выбираю между samsung и lg. У первых экраны приятней (по углам обзора), а у вторых выше функциональность (с usb кушают любой формат). Я не понял где вы находитесь, но выбор корейских марок, как мне кажется, везде максимальный.
    Ответ написан
    5 комментариев