• Как контролировать память кортежей?

    @basrach
    В приведенном примере проблемы нет, утечки быть не может. Если утечка 100% есть, то скорее всего, когда создавали этот пример на основе реального кода, вы упустили важную деталь из-за которой и происходит утечка.
    Ответ написан
  • Как удалить первые 12 байт массива?

    @basrach
    byte[] array = ...
    array = array.Skip(12).ToArray();
    Ответ написан
    Комментировать
  • Как использовать async/await в DI контейнере ASP.NET CORE?

    @basrach
    Посмотрите на сигнатуру второго вызова AddScoped. В Visual Studio это можно сделать наведя указатель на метод.
    Она будет такой: AddScoped>(x => ... Т.е. в контейнере регистрируется не Some, а Task. И это нормально, асинхронный метод всегда возвращает Task. Чтобы зарегистрировать Some, нужно чтобы лямбда внутри AddScoped была синхронная, этого можно достичь написав либо ...GetSomeAsync().Result, либо еще как-то получить результат, и непосредственно его уже возвратить.
    Ответ написан
    Комментировать
  • Нарушаю ли я ООП используя partial классы?

    @basrach
    Нет.
    Partail классы это механизм компилятора. А ООП стиль написания программ. Понятия из разных областей и не пересекаются никак.
    Ответ написан
    Комментировать
  • Как правильно написать метод?

    @basrach
    Ха!
    Методы #2, #3 и #4 абсолютно одинаковые, но результаты в таблице для #2 отличаются от последних в 6 раз.
    Это значит, что ваши замеры годятся только чтобы подтереть кое-что.
    Ответ написан
    Комментировать
  • В последних версиях .net что-то изменили в зависимостях сборок?

    @basrach
    Всегда так работало. Т.е. ссылка на Project3 не обязана быть в Project1.
    Скорее всего ваша проблема имела другую причину. Но лечилась добавлением ссылки на Project3. Возможно поэтому вы так подумали.
    Ответ написан
    Комментировать
  • Какими сервисами/программами перевести часовой аудиофайл в (русскоязычный) текст?

    @basrach
    Биржа труда фрилансеров - единственный сервис который тут на самом деле может помочь.
    Ответ написан
    Комментировать
  • Как сделать повторный вызов метода?

    @basrach
    Если хочется "четко и красава чтоб не хуже чем у пацанов", гляньте на либу Polly:
    public async Task<List<AccountListView>> GetAsync()
    {
    	var policy = Policy
    		.Handle<UnauthorizedException>()
    		.RetryAsync(
    			retryCount: 1,
    			onRetryAsync: (e, i) => Context.Renew());
    
    	return await policy.ExecuteAsync(TryGetAccountListAsync);
    }


    Созданную policy можно переиспользовать. Т.е. вам не придется больше плодить копипасту, достаточно объявить одну политику на приложение, и дальше просто вызывайте то что требует обновления токена через эту политику.
    Ответ написан
    2 комментария
  • ASP.NET Core: сколько должно быть конфигов дли разных баз данных и как их распределить по контроллерам?

    @basrach
    Вам нужны два разных контекста. Контексты, это те классы, которые наследуются от DbContext, и абстрагируют доступ к БД. Один для одной базы, другой для второй базы. Соответственно и конфигов у вас будет по числу баз данных, т.е. тоже два.
    Ответ написан
    Комментировать
  • Вопросы по Clean Architecture?

    @basrach
    Есть два варианта.

    Первый заключается в том, чтобы выгружать из БД всю коллекцию тегов. В данном случае такое решение будет вполне оправданным. Поскольку обычно задачи, и вообще что-либо, содержат 3-5 тегов, максимум 7-10, очень редко больше. В таком случае вполне нормально сделать свойство Tags у сущности Task и ожидать, что там будут всегда все теги данной задачи. Т.е. всегда загружать коллекцию тегов для задачи при восстановлении задачи из БД.

    Второй заключается в том, чтобы вынести логику в Service. CA и подобные архитектуры диктуют лишь то, что бизнес логика (БЛ) должна быть первична, а все остальное вторично и подстраивается под БЛ. Но они не ограничивают в средствах выражения, т.е. необязательно чтобы вся БЛ была в методах сущностей. Наоборот, внутри сущностей должна быть лишь простая логика, а все что посложнее выносится в Domain Service-ы.
    Например, можно создать TaskService, в котором будет метод AddNewTagToTask(Tag tag, Task task). Так как это сервис, то здесь можно иметь зависимость на соответствующий репозиторий, и тогда можно проверить наличие тега с помощью него: if (!taskRepository.TaskHaveTag(tag)) { ... }

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

    Но стоит заметить, что если выбран второй подход, то стоит убрать свойство Tags из сущности Task. Так как это будет обманом. Представьте, что вы решили не загружать все теги для задачи, а сделать проверку через сервис. Но в проекте вы работаете не один. Другой же программист увидит что есть поле Tags у задачи и попытается использовать его так, как-будто там там содержатся все теги для задачи. Поэтому чтобы не создавать двусмысленности нужно убрать свойство Tags из Task.
    Ответ написан
    2 комментария
  • Как ограничить количество одновременно запускаемых потоков?

    @basrach
    Самый простой вариант это использовать Parallel.Foreach.
    var myEntities = new MyEntity[100];
    var maxThreads = 15;
    
    System.Threading.Tasks.Parallel.ForEach(
        myEntities,
        new System.Threading.Tasks.ParallelOptions { MaxDegreeOfParallelism = maxThreads },
        entity =>
        {
            entity.Do()
        });


    Второй вариант использовать Semaphore или SemaphoreSlim.
    var myEntities = new MyEntity[100];
    var maxThreads = 15;	
    
    var semaphoreSlim = new SemaphoreSlim(maxThreads);
    var tasks = new List<Task>(myEntities.Length);
    foreach (var entity in myEntities)
    {
    	tasks.Add(Task.Run(() =>
    	{
    		semaphoreSlim.Wait();
    		try
    		{
    			entity.Do();
    		}
    		finally
    		{
    			semaphoreSlim.Release();	
    		}
    	}));
    }
    
    Task.WaitAll(tasks.ToArray());


    Если вы хотите использовать класс Thread напрямую, то
    var myEntities = new MyEntity[100];
    var maxThreads = 3;	
    
    var semaphore = new Semaphore(maxThreads, maxThreads);
    var threads = new List<Thread>(myEntities.Length);
    foreach (var entity in myEntities)
    {
    	var thread = new Thread(() =>
    	{
    		semaphore.WaitOne();
    		try
    		{
    			entity.Do();
    		}
    		finally
    		{
    			semaphore.Release();
    		}
    	});
    	
    	threads.Add(thread);
    	
    	thread.Start();
    }
    
    foreach (var thread in threads)
    	thread.Join();


    Хотя из условий задачи кажется, что здесь вполне можно обойтись Task. Task предпочтительней еще и по той причине, что потоки переиспользуются. Т.е. задействованных потоков будет столько, сколько одновременно выполняется задач, например 15. В случае же создания потока напрямую через класс Thread, 15 будут работать, остальные просто ждать, при этом все равно расходуя ресурсы.
    Ответ написан
    Комментировать
  • Почему не инициализируются свойства сервиса при добавлении через AddTransient в ASP.NET Core?

    @basrach
    Потому что встроенный DI контейнер ASP. Net Core не поддерживает инъекцию свойств и полей.
    А методом services.Configure вы на самом деле регистрируете опции, которые можно потом получить так: IOptions
    Т.е. вам нужно сделать так:
    services.AddTransient<IEmailService, EmailService>();
    services.Configure<EmailServiceOptions>(options =>
    {
        options._emailAddress = "email";
        options._emailPassword = "password";
        options._name = "name";
    });
    
    class EmailService
    {
      public EmailService(IOptions<EmailServiceOptions> optionsAccessor)
      {
        _emailAddress = optionsAcessor.Value.EmailAddress;
        ....
      }
    }
    Ответ написан
    1 комментарий
  • MS SQL запрос по группировке?

    @basrach
    select count(*) as 'кол-во уникальных компаний в которых есть хоть одна закрытая задача'
    from Department d
    join Contact c on c.DepartmentId = d.Id
    where
        d.Id in (
    		'9b90c192-60e6-df11-971b-001d60e938c6', 
    		'66ffa487-b4da-df11-9b2a-001d60e938c6', 
    		'2076c4b6-7fe6-df11-971b-001d60e938c6', 
    		'b5f90312-8bc4-415a-ab4f-e311b35bf699')
    	and exists(
    		select 1 as [closed_activity]
    		from Activity a
    		where
                a.OwnerId = c.Id
                and a.ModifiedOn between '2018-06-01' and '2018-06-30'
                and a.ResultId = '632AFDD2-F616-4EA6-87D2-8ED38EED8AFF'
    	)
    Ответ написан
  • Почему не работает коммуникация между клиентом и сервером?

    @basrach
    Навскидку есть несколько подозрительных мест:
    1. Флаг _isWaitResponce в методе SendMessageFromQueue класса TcpCommunicatorBase, который запрещает отправку если поднят (имеет значение true). При этом сбрасывается он только после получения ответа, и то не гарантированно, для этого нужно чтобы выполнился ряд условий, и он не сбросится в случае исключения. Таким образом этот флаг может быть причиной ошибки, если клиент не получил ответа после отправки, либо при получении ответа произошла ошибка.
    2. Флаг inRead в методе BeginListenForMessage того же класса. Этот флаг также запрещает чтение если поднят, и гарантированно не сбрасывается. Т.е. может остаться в состоянии true если произошло исключение про чтении сообщения. Соответственно сломанное чтение на клиенте может заблокировать отправку.
    3. В CustomSynchronizationContext с хабра есть баг, когда сообщение может висеть в очереди потока и не обрабатываться до тех пор, пока не придет еще одно.

    PS.
    Имхо, в целом код не выглядит надежным. Когда отправка завязана на получение, и все это в одном классе, и для обоих процессов используются те же переменные, всё это резко усложняет понимание и отладку, и снижает надежность кода.
    Ответ написан
    Комментировать
  • System.IO.FileNotFoundException: "Невозможно загрузить файл или сборку "sorttbls.nlp" или один из зависимых от них компонентов. Что делать?

    @basrach
    ...файл или сборку «sorttbls.nlp» или один из зависимых от них компонентов...
    - чего-то не хватает, либо самого «sorttbls.nlp», либо еще чего-то. Что делать? - искать то, чего недостает. Если вы уже пользуетесь декомпилятором, то в нем должна быть функция просмотра зависимостей, сравните список зависимостей с тем, что у вас в билд директории.
    Ответ написан
    Комментировать
  • Что почитать по MS SQL?

    @basrach
    Вот хорошая книжка Pro SQL Server Internals by Dmitri Korotkevitch
    Ответ написан
    Комментировать
  • Как собрать .NET Core проект под ubuntu в один файл?

    @basrach
    Это относится не только к Core под Ubuntu. К обычному .Net под Windows это тоже относится.
    Решают эту проблему добавлением всех зависимостей исполняемого файла (например .exe) в ресурсы этого самого .exe. Затем при запуске приложения регистрируется обработчик события AppDomain.AssemblyResolve, который достаёт нужную сборку из ресурсов, загружает ее в домен и возвращает ссылку на нее среде. AppDomain.AssemblyResolve вызывается каждый раз когда приложению нужна какая-нибудь зависимость.
    Это просто и несложно реализуется, при этом это не займет много времени.
    Также есть и библиотеки, которые встраиваются в процесс билда и позволяют это дело автоматизировать. Выше уже был упомянут ILMerge, также есть Fody, возможно есть еще какие-то аналоги.
    Ответ написан
    Комментировать
  • Как убрать полный путь до файлов проекта .NET Core в исключениях?

    @basrach
    Эта информация хранится в файлах с расширением *.pdb. Они нужны для дебагера. Удалить часть пути из них невозможно, но можно удалить файл целиком и тогда в исключениях не будет информации об исходном коде вообще, будет только стек вызовов (имя класса, название метода и т.п.). Также можно в .csproj добавить условие, чтобы при релизном билде эти файлы не создавались:
    <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
      <DebugType>none</DebugType>
      <DebugSymbols>false</DebugSymbols>
    </PropertyGroup>

    В основном эти файлы нужны для дебага. Без них дебаггер не будет корректно работать, т.е. он не сможет сопоставить в общем случае инструкцию с исходным кодом. Соотвественно не в релизе отключать генерацию этих файлов не стоит.
    Ответ написан
    Комментировать
  • Когда используете принудительную сборку мусора?

    @basrach
    Вызов GC.Collect() нужен для сборки объектов в 1 и во 2 поколениях. То что в 0 поколении и так прекрасно собирается. Но то что переживает 0-вое поколение, т.е. объекты в 1-ом и во 2-ом поколениях, очень редко удостаиваются внимания сборщика, если нет жесткого прессинга по памяти. При этом, очень большие объекты, в том числе массивы, при создании помещаются сразу в кучу во 2-ое поколение.
    Соответственно, нужно чтобы совпало:
    1) В программе есть некоторая операция, которая создает очень большой объект, такой, что он сразу попадает во 2-ое поколение.
    2) Свободной памяти на сервере больше нет, либо очень мало.
    3) Нужно избежать простоя, связанного со сборкой мусора, при запуске следующей подобной операции.
    4) В некоторой точке программы точно можно гарантировать, что нет ни одной ссылки на тот большой объект (иначе GC его не удалит)
    И только тогда можно дернуть GC.Collect(). Иначе смысла вызывать его нет.
    Т.е. вы на сто процентов уверены, что будет задержка вызванная сборкой мусора, и именно тем, что сборщик полезет чистить 1-ое и 2-ое поколение, но вас не устраивает то, когда именно произойдет эта задержка, и вы переносите её на более ранее время (возможно более подходящее/приемлемое) принудительным вызовом GC.Collect().
    Главное нужно понимать, что GC.Collect() волшебным образом не очистит память. Чтобы этот вызов что-то почистил нужно быть на 100% уверены, что в памяти есть объекты на которые нет ссылок, но которые застряли в памяти. Иными словами, что нет утечек памяти. (да да, программы на дот.нет тоже могут течь) Как правило, если устранить утечки, т.е. выстроить правильную работу с памятью, то потребность принудительно указывать сборщику мусора отпадет сама собой.
    Ответ написан
    Комментировать
  • Как ускорить время запуска первой страницы (страницы авторизации)?

    @basrach
    Если задержка 5-7 секунд, то скорее всего это связано с остановкой ApplicationPool-а. При отсутствии запросов в течении некоторого времени (по умолчанию 20 мин) IIS останавливает процесс, который обслуживает ап-пул сайта. Соответственно, если приходит запрос и пул остановлен, то IIS-у нужно запустить процесс, поднять все модули для сайта, сам сайт загрузить и запустить, и только после всего этого сайт будет готов обрабатывать запросы. Отсюда такая значительная задержка при первом запросе, все последующие запросы будут обрабатываться быстро.
    Чтобы изменить это поведение нужно в IIS-Manager выбрать пул, затем Advanced Settings и там два параметра: "Idle Time-out" и "Idle Time-out Action". Последний отвечает за действие после истечения таймаута, по умолчанию там стоит Terminate, т.е. прерывать процесс, можно изменить на Suspend (приостановить но не убивать процесс). Также там есть параметр "Start Mode", и там стоит по умолчанию OnDemand (по запросу), можно изменить на AlwaysRunning (т.е. всегда запущен).
    Но стоит учесть, что постоянно запущенный процесс ап-пула будет потреблять немало памяти и некоторое количество процессорного времени, и если приложение используется редко, то по сути в холостую расходовать ресурсы сервера.
    Ответ написан
    1 комментарий