Пользователь пока ничего не рассказал о себе

Достижения

Все достижения (6)

Наибольший вклад в теги

Все теги (38)

Лучшие ответы пользователя

Все ответы (30)
  • Генерация дерева для каталогов, рекурсия?

    Ogoun
    @Ogoun
    Programmer
    var list = new List<string>();
    FillFolderList("C:\\", list, 0, 3, 3);
    
    
    public static void FillFolderList(string path, List<string> list, int current_level, int depth, int width)
    {
        list.Add(path);
        if (current_level >= depth) return;
        int current_width = 0;
        try
        {
            foreach (var subdir in Directory.GetDirectories(path))
            {
                FillFolderList(subdir, list, current_level + 1, depth, width);
                current_width++;
                if (current_width > width) break;
            }
        }
        catch (Exception)
        {
        }
    }
    Ответ написан
    3 комментария
  • Разумен ли self-hosting ASP.NET Web API приложения в службе Windows? Кто-нибудь использовал такое в проде?

    Ogoun
    @Ogoun
    Programmer
    Использую именно такой подход в проде, сервисы работаю как виндовс-службы, при старте сервис выбирает себе свободный порт и поднимает self-host webapi, по которому к нему может обращаться любой другой сервис. По скорости пока хватает, но планирую перейти на свой бинарный протокол сразу поверх TCP (по тестам до 20000 RPS получается добраться, на webapi до такого не дотянуть).
    Ответ написан
    7 комментариев
  • CodeFirst, как получить из базового объекта наследуемые?

    Ogoun
    @Ogoun
    Programmer
    public abstract class Product
        {
            public int ProductId { get; set; }
            public string Name { get; set; }
    
            public abstract int GetShopPrice(City city);
        }
    
        public sealed class SimpleProduct : Product
        {
            public override int GetShopPrice(City city)
            {
                //логика
            }
        }
        public sealed class ModuleProduct : Product
        {
            public override int GetShopPrice(City city)
            {
                //логика
            }
        }
    Ответ написан
    Комментировать
  • Как залочить файл в JScript(WSH)?

    Ogoun
    @Ogoun Автор вопроса
    Programmer
    Решил вопрос, надо было открывать не на чтение, при проверкке блокировки, а также на добавление.

    
    var fso = new ActiveXObject('Scripting.FileSystemObject');
    var Lockeds = new ActiveXObject("Scripting.Dictionary");
    
    LockFile("2.ini");
    CheckLocking("2.ini");
    UnLockFile("2.ini");
    CheckLocking("2.ini");
    
    WScript.Quit();
    
    function LockFile(path) {
        if (!Lockeds.Exists(path)) {
            Lockeds.Add(path, fso.OpenTextFile(path, 8));
        }
    }
    
    function CheckLocking(path) {
        try {
            var t = fso.OpenTextFile(path, 8);
            t.Close();
            return false;
        }
        catch (e) {
        }
        return true;
    }
    
    
    function UnLockFile(path) {
        if (Lockeds.Exists(path)) {
            Lockeds.Item(path).Close();
            Lockeds.Remove(path);
        }
    }
    
    Ответ написан
    Комментировать
  • Есть ли такой реализованный список на C#?

    Ogoun
    @Ogoun
    Programmer
    Для решения подобной задачи я использовал свое решение, где делал односвязный список объектов, обертывающих мой объект и добавляющих поле с временем удаления. Класс со списком объектов содержит один таймер, из Threading. При добавлении нового объекта он вставляется с сортировкой по дате, т.е. первый объект в списке всегда с самым коротким временем жизни, при добавлении/удалении перерасчитывается таймер. В итоге ресурсов потребляется мало, но сложность вставки/удаления O(N)

    Вот упрощенный рабочий пример:
    internal class TemporaryObject
    {
        private static long _counter = 0;
        public long Key { get; private set; }
        public TemporaryObject()
        {
            Key = Interlocked.Increment(ref _counter);
        }
        /// <summary>
        /// Событие при завершении ожидания
        /// </summary>
        public Action Callback;
        /// <summary>
        /// Срок истечения ожидания
        /// </summary>
        public DateTime ExpirationDate;
        /// <summary>
        /// Следующий объект с ближайшей датой окончания ожидания
        /// </summary>
        public TemporaryObject Next;
    }
    
    public class TemporaryObjectPool
    {
        private readonly object _locker = new object();
        /// <summary>
        /// Таймер. Один на всех
        /// </summary>
        private Timer _timer;
        /// <summary>
        /// Объект с ближайшей датой окончания ожидания
        /// </summary>
        private TemporaryObject _current = null;
        /// <summary>
        /// Переустановка таймера
        /// </summary>
        private void ResetTimer()
        {
            if (null != _current)
            {
                var diff = (_current.ExpirationDate - DateTime.Now).TotalMilliseconds;
                if (diff < 0) diff = 0;
                _timer.Change((int)diff, Timeout.Infinite);
            }
            else
            {
                _timer.Change(Timeout.Infinite, Timeout.Infinite);
            }
        }
    
        public TemporaryObjectPool()
        {
            _timer = new Timer(state =>
            {
                Action action = null;
                lock (_locker)
                {
                    if (null != _current)
                    {
                        // Получаем событие для исполнения
                        action = _current.Callback;
                        // Находим следующий ожидающий объект
                        _current = _current.Next;
                        // Перезадание таймера
                        ResetTimer();
                    }
                }
                // Вызов события ожидавшего даты
                if (null != action)
                {
                    ThreadPool.QueueUserWorkItem(s => action());
                }
            }, null, Timeout.Infinite, Timeout.Infinite);
        }
    
        /// <summary>
        /// Добавление ожидающего объекта
        /// </summary>
        /// <param name="insert"></param>
        internal long Push(TemporaryObject insert)
        {
            lock (_locker)
            {
                // Если пул пуст, то добавляемое событие становится корневым
                if (null == _current)
                {
                    _current = insert;
                }
                else
                {
                    // Если пул не пуст
                    var cursor = _current;
                    TemporaryObject prev = null;
                    // Поиск места для вставки, сложность вставки O(n) в худшем случае
                    do
                    {
                        if (DateTime.Compare(cursor.ExpirationDate, insert.ExpirationDate) > 0)
                        {
                            insert.Next = cursor;
                            if (null == prev)
                            {
                                _current = insert;
                            }
                            else
                            {
                                prev.Next = insert;
                            }
                            break;
                        }
                        prev = cursor;
                        cursor = cursor.Next;
                        if (cursor == null)
                        {
                            prev.Next = insert;
                        }
                    } while (cursor != null);
                }
                ResetTimer();
            }
            return insert.Key;
        }
    
        public void Remove(long key)
        {
            lock (_locker)
            {
                if (_current == null) return;
                bool removed = false;
                if (_current.Key == key)
                {
                    _current = _current.Next;
                    removed = true;
                }
                else
                {
                    var prev = _current;
                    var next = _current.Next;
                    while (next != null)
                    {
                        if (next.Key == key)
                        {
                            prev.Next = next.Next;
                            removed = true;
                            break;
                        }
                        prev = next;
                        next = next.Next;
                    }
                }
                if (removed)
                {
                    ResetTimer();
                }
            }
        }
    }


    И использование
    var pool = new TemporaryObjectPool();
    pool.Push(new TemporaryObject { Callback = () => Console.WriteLine("#1 removed"), ExpirationDate = DateTime.Now.AddSeconds(5) });
    pool.Push(new TemporaryObject { Callback = () => Console.WriteLine("#2 removed"), ExpirationDate = DateTime.Now.AddSeconds(10) });
    pool.Push(new TemporaryObject { Callback = () => Console.WriteLine("#3 removed"), ExpirationDate = DateTime.Now.AddSeconds(15) });
    Ответ написан
    Комментировать

Лучшие вопросы пользователя

Все вопросы (22)