Ответы пользователя по тегу .NET
  • Как реализовать ожидание готовности выполнения метода без использования цикла while?

    lam0x86
    @lam0x86
    Если я правильно понимаю, обработчик сообщений от websocket'а у вас крутится где-то в другом месте. Вы можете создать общий TaskCompletionSource и в методе Run вызвать await tcs.Task;, а при приходе сообщения по сокету вызывать tcs.SetResult();.
    Ответ написан
    Комментировать
  • Какой тип лучше подходит для хранения времени?

    lam0x86
    @lam0x86
    Я бы тоже использовал TimeSpan, или обернул его в свой тип. Как альтернатива - использовать тип LocalTime из библиотеки Noda Time, который как раз предназначен для хранения времени суток. Но это пушкой по воробьям.
    Ответ написан
    Комментировать
  • Для написания полноценного телеграм бота на c# надо юзать ASP.NET?

    lam0x86
    @lam0x86
    Для получения сообщений с серверов Телеграма, их API поддерживает два типа соединения:
    1) long polling - когда бот подключается к telegram-серверам, отправляет http-запрос и ждёт данных. Когда данные пришли, он кидает новый запрос и снова ждёт.
    2) webhooks - когда серверы Телеграма сами дёргают URL, который ты зарегистрируешь.

    Решение (1) удобно для тестирования, но менее производительно и плохо масштабируется на несколько серверов, поэтому чаще используют (2).
    Но (2) требует HTTPS и наличие веб-сервера, который будет обрабатывать входящие запросы от серверов Телеграма. Писать консольное приложение со встроенным веб-сервером, конечно, можно, но тогда мы теряем все преимущества ASP.NET-а.
    Например, IIS умеет автоматически перезапускать веб-сайт при его случайном падении или при перезагрузке сервера. Для консольного приложения придётся писать свой watch dog.
    Ещё в IIS можно настроить балансировку нагрузки так, чтобы запросы от телеграма обрабатывались разными серверами. Для консоли надо опять же писать свой балансировщик, который тоже может упасть в самый неподходящий момент.
    Ответ написан
    Комментировать
  • Как организовать процесс при копировании?

    lam0x86
    @lam0x86
    Во-первых, производить длительные операции (больше 100 миллисекунд) в UI-потоке - плохой тон. Приложение будет подвисать, пока файл не скопируется. Чтобы этого избежать, все дисковые операции должны быть асинхронны (вместо async/await можно использовать FileStream.BeginRead/EndRead).
    Во-вторых, у вас слишком большой буфер. 2^19 - это 512 килобайт. Возможно, вы копируете файлы меньшего размера, поэтому всё копирование происходит в одну операцию чтения. Попробуйте буфер, скажем, в 16кб.
    Ответ написан
    1 комментарий
  • С чего лучше начинать VisualBasic или C#?

    lam0x86
    @lam0x86
    VisualBasic (тот, что .NET) почти ничем не отличается от C#, кроме синтаксиса. Есть даже конвертеры из одного языка в другой - пишете программу на VB, получаете на выходе C# (и наоборот). Но я не советую начинать с VB, так как это фактически мёртвый язык, несмотря на то, что в самом авторитетном рейтинге популярности языков программирования он выше C#. Причина тому - США. Там до сих пор активно нанимают VB-разработчиков, которым приходится поддерживать устаревший код. Особенно это касается банковского сектора. Платят за VB больше, но копаться в легаси - то ещё удовольствие.
    В общем, учитывая, что оба языка - детища Microsoft, и что сама компания активно продвигает C#, лучше сразу начинать с него.
    Ответ написан
    Комментировать
  • Многопоточность ON DEMAND, или однопоточная многопоточность?

    lam0x86
    @lam0x86
    У меня получился вот такой велосипед:

    using System;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    using System.Diagnostics;
    
    namespace ThreadsTests
    {
        public class WorkData
        {
            public int Id;
        }
    
        public abstract class ProtoBase<T>
        {
            private static int NextId;
            
            private TaskCompletionSource<T> _dataTaskCompletionSource = new TaskCompletionSource<T>();
    
            public int give_count = 1;
    
            protected ProtoBase()
            {
                Id = ++NextId;
                new Task(Parse).Start();
            }
            
            public int Id { get; }
    
            public bool IsFinish { get; private set; }
    
            protected void Finish()
            {
                IsFinish = true;
            }
    
            public async Task PushData(T data)
            {
                _dataTaskCompletionSource.SetResult(data);
                await Task.Yield();
            }
    
            protected async Task<T> GetNextData()
            {
                var taskResult = await _dataTaskCompletionSource.Task;
                _dataTaskCompletionSource = new TaskCompletionSource<T>();
                return taskResult;
            }
    
            protected abstract void Parse();
        }
    
        public class TestWorker : ProtoBase<WorkData>
        {
            protected override async void Parse()
            {
    
                WorkData data = await GetNextData();
                Trace.TraceInformation("{0:N0} take 1 [id={1:N0}]", Id, data.Id);
                data = await GetNextData();
                Trace.TraceInformation("{0:N0} take 2 [id={1:N0}]", Id, data.Id);
                data = await GetNextData();
                Trace.TraceInformation("{0:N0} take 3 [id={1:N0}]", Id, data.Id);
                Finish();
                Trace.TraceInformation("{0:N0} Finish ххх", Id);
            }
        }
    
    
        public class Program
        {
            public static async Task Main(string[] args)
            {
                var schedulerPair = new ConcurrentExclusiveSchedulerPair();
                await await Task.Factory.StartNew(
                    AsyncWorkersTest,
                    CancellationToken.None,
                    TaskCreationOptions.None,
                    schedulerPair.ExclusiveScheduler);
                Console.WriteLine("FINISHED");
                Console.ReadKey();
            }
            
            public static async Task AsyncWorkersTest()
            {
                //workers count
                const int testCount = 1000; // 100, 1000, 10000, 100000
                var Workers = new List<TestWorker>();
    
                for (int i = 0; i < testCount; i++)
                {
                    Workers.Add(new TestWorker());
                }
    
                Random rnd = new Random();
    
                int getDataCount = testCount * 3;
                for (int i = 0; i < getDataCount; i++)
                {
                    int ind = rnd.Next(0, Workers.Count);
                    WorkData wd = new WorkData() { Id = i };
                    
                    if (Workers[ind].IsFinish) continue;
                    Trace.TraceInformation("{0:N0} push {1} [id={2:N0}]", Workers[ind].Id, Workers[ind].give_count++, wd.Id);
                    await Workers[ind].PushData(wd);
                }
            }
        }
    }


    Вывод:
    ConsoleApp1 Information: 0 : 1 push 1 [id=0]
    ConsoleApp1 Information: 0 : 1 take 1 [id=0]
    ConsoleApp1 Information: 0 : 2 push 1 [id=1]
    ConsoleApp1 Information: 0 : 2 take 1 [id=1]
    ConsoleApp1 Information: 0 : 1 push 2 [id=2]
    ConsoleApp1 Information: 0 : 1 take 2 [id=2]
    ConsoleApp1 Information: 0 : 1 push 3 [id=3]
    ConsoleApp1 Information: 0 : 1 take 3 [id=3]
    ConsoleApp1 Information: 0 : 1 Finish ххх
    ConsoleApp1 Information: 0 : 2 push 2 [id=4]
    ConsoleApp1 Information: 0 : 2 take 2 [id=4]
    ConsoleApp1 Information: 0 : 2 push 3 [id=5]
    ConsoleApp1 Information: 0 : 2 take 3 [id=5]
    ConsoleApp1 Information: 0 : 2 Finish ххх
    Ответ написан
  • Как добавить dll в конечную сборку c#?

    lam0x86
    @lam0x86
    Install-Package MSBuild.ILMerge.Task
    Ответ написан
    Комментировать
  • Как красиво реализовать возможность подписания блока данных?

    lam0x86
    @lam0x86
    Как я понял задачу: у вас есть две сущности, реализация которых неизвестна:
    • подписываемый объект
    • сервис генерации подписи

    Объект ничего не знает, каким сервисом он будет подписан, а сервис не знает, какая структура у подписываемого объекта.
    В этом случае логично ввести некую промежуточную сущность, в которую объект может себя сериализовать, а сервис будет знать, как её подписать. В простейшем случае это может быть массив, например, byte[]. Можно придумать более изощренный способ с потоковой генерацией подписи, чтобы не создавать промежуточный объект.

    Может, я неправильно понял задачу, но вот, что у меня вышло.

    Интерфейсы:
    public interface ISignable
    {
        ISignature Signature { get; set; }
        byte[] Serialize();
    }
    
    public interface ISignature
    {
    }
    
    public interface ISignatureService
    {
        bool Validate(ISignable signable);
        void Sign(ISignable signable);
    }


    Простейшая имплементация (в качестве подписи используется просто хеш-код):
    class MyObject : ISignable
    {
        public ISignature Signature { get; set; }
        public long Param1 { get; set; }
        public string Param2 { get; set; }
        public string InnerData { get; set; }
    
        public byte[] Serialize()
        {
            return Encoding.UTF8.GetBytes(Param1 + Param2 + InnerData);
        }
    }
    
    public class HashCodeSignatureService : ISignatureService
    {
        public void Sign(ISignable signable)
        {
            var signature = CalculateSignature(signable);
            signable.Signature = signature;
        }
    
        public bool Validate(ISignable signable)
        {
            var s1 = CalculateSignature(signable);
            var s2 = signable.Signature as SimpleHashCodeSignature;
            return s1?.HashCode == s2?.HashCode;
        }
    
        private static SimpleHashCodeSignature CalculateSignature(ISignable signable)
        {
            var body = signable.Serialize();
            var signature = new SimpleHashCodeSignature(body.Aggregate(0, (a, b) => a + b.GetHashCode()));
            return signature;
        }
    }
    
    public class SimpleHashCodeSignature : ISignature
    {
        public int HashCode { get; }
    
        public SimpleHashCodeSignature(int hashCode)
        {
            HashCode = hashCode;
        }
    }


    А так это можно использовать:
    class Program
    {
        static void Main(string[] args)
        {
            var obj = new MyObject {Param1 = 1, Param2 = "asd", InnerData = "some data"};
            var signatureService = new HashCodeSignatureService();
            signatureService.Sign(obj);
            // Passing the object across untrusted boundary
            signatureService.Validate(obj);
        }
    }
    Ответ написан
    Комментировать
  • Как реализовать строчную отладку кода в C#?

    lam0x86
    @lam0x86
    На самом деле, ничего сложного. Надо просто указать скрипту генерировать DebugInformation и указать путь к временному файлу с исходным кодом (студия не умеет дебажить исходники с памяти).

    Вот пример:

    class Program
        {
            static void Main(string[] args)
            {
                string scriptFileName = Path.GetTempFileName() + ".cs";
    
                var scriptBody = GenerateScript(scriptFileName);
    
                var script = CSharpScript.Create(
                    scriptBody,
                    globalsType: typeof(Globals),
                    options: ScriptOptions
                             .Default
                             .WithEmitDebugInformation(true)
                             .WithFilePath(scriptFileName)
                             .WithFileEncoding(Encoding.UTF8));
    
                var sum = script.RunAsync(new Globals {X = 56, Y = 42}).Result.ReturnValue;
    
                Console.Out.WriteLine(sum);
                Console.ReadKey();
    
                File.Delete(scriptFileName);
            }
    
            private static string GenerateScript(string fileName)
            {
                var body = 
    @"var result = X + Y;
    return result;
    ";
    
                File.WriteAllText(fileName, body, Encoding.UTF8);
    
                return body;
            }
        }
    
        public class Globals
        {
            public int X { get; set; }
    
            public int Y { get; set; }
        }
    Ответ написан
    Комментировать
  • Как на C# реализовать асинхронную очередь задач у объекта?

    lam0x86
    @lam0x86
    class Program
        {
            static void Main(string[] args)
            {
                MainAsync(args).GetAwaiter().GetResult();
    
                Console.ReadKey();
            }
    
            static async Task MainAsync(string[] args)
            {
                HardWorker hardWorker1 = new HardWorker();
                HardWorker hardWorker2 = new HardWorker();
                HardWorker hardWorker3 = new HardWorker();
                HardWorker hardWorker4 = new HardWorker();
                HardWorker hardWorker5 = new HardWorker();
    
                Task t1 = Task.CompletedTask;
                Task t2 = Task.CompletedTask;
                Task t3 = Task.CompletedTask;
                Task t4 = Task.CompletedTask;
                Task t5 = Task.CompletedTask;
    
                Random rand = new Random();
    
                for (int i = 0; i < 50; i++)
                {
                    t1 = t1.ContinueWith(task => hardWorker1.DoSomething(1, rand.Next(1, 10000)));
                    t2 = t2.ContinueWith(task => hardWorker2.DoSomething(2, rand.Next(1, 10000)));
                    t3 = t3.ContinueWith(task => hardWorker3.DoSomething(3, rand.Next(1, 10000)));
                    t4 = t4.ContinueWith(task => hardWorker4.DoSomething(4, rand.Next(1, 10000)));
                    t5 = t5.ContinueWith(task => hardWorker5.DoSomething(5, rand.Next(1, 10000)));
                }
    
                await Task.WhenAll(t1, t2, t3, t4, t5);
            }
        }
    
        public class HardWorker : AbstractHardWorker
        {
            public void DoSomething(int task, int time)
            {
                Console.Out.WriteLine("Start: " + task);
                Thread.Sleep(time);
                Console.Out.WriteLine("End: " + task);
            }
        }
    
        public interface AbstractHardWorker
        {
            void DoSomething(int task, int time);
        }
    Ответ написан
    3 комментария
  • Почему не обрабатывается файл блоками?

    lam0x86
    @lam0x86
    Возможно, вместо
    var bytes1 = new byte[writeStream.Length];
    writeStream.Read(bytes1, 0, bytes1.Length);
    writer.Write(bytes1, 0, bytes1.Length);

    следует написать что-то типа
    writeStream.Position = 0;
    writeStream.CopyTo(writer);
    Ответ написан
  • С# .Net 3.5 - есть ли возможность не внедрять сгенерированные Interop .dll файлы?

    lam0x86
    @lam0x86
    Декомпилируйте сгенерированную interop-сборку и добавьте её в свой проект.
    Ответ написан
    2 комментария
  • Как определить что элемент в рабочей области?

    lam0x86
    @lam0x86
    Вообще, в WPF с виртуализацией данных всё довольно печально. Из-за её отсутствия и расплодилось такое количество сторонних гридов. Но тем не менее, можно подписаться на события ItemContainerGenerator-а, который отвечает за визуальную виртуализацию, и подгружать данные во время появления контейнера строк на экране.
    Ответ написан
    Комментировать
  • Алгоритмический вопрос от будущего C#.NET-джуниора. С чего начать исследование?

    lam0x86
    @lam0x86
    Последовательность действий такая:
    1) разбиение текста на лексические единицы (в вашем случае значимыми единицами являются слова). Удобно на выходе получать IEnumerable, представляющий ленивый итератор по словам в тексте.
    2) приведение слова к нормальной форме, т. е. к нижнему регистру и, опционально, к общей словоформе (например, для существительных - им. падеж, ед. число, и т.д.)
    3) добавление слова в Dictionary, где ключом является само слово, а значением - счётчик:
    int count;
    dictionary.TryGetValue(word, out count);
    dictionary[word] = count + 1;
    Ответ написан
    Комментировать
  • Как выстроить приложение .NET с большим числом циклично изменяющихся элементов?

    lam0x86
    @lam0x86
    В RX есть отличный набор классов с общим интерфейсом IScheduler, которые позволяют планировать задачи на исполнение в нужное время и с нужным интервалом. В Вашем случае подойдёт TaskPoolScheduler.
    Но вообще, в играх часто используют подход с обычным циклом, в котором происходит обработка очередного игрового кадра. На каждой итерации определяется игровое время, и на его основе обрабатываются события.
    Ответ написан
    Комментировать
  • Какие посмотреть образцовые open-source проекты на WPF?

    lam0x86
    @lam0x86
    Я бы посоветовал почитать про Prism: msdn.microsoft.com/en-us/library/gg406140.aspx
    Хоть это и не готовое приложение, но из документации можно почерпнуть много полезных шаблонов, которые применяются в разработке под WPF.
    Ответ написан
  • Как для двух combobox использовать один List?

    lam0x86
    @lam0x86
    comboBox1.DataSource = new BindingSource() {DataSource = list};
    comboBox2.DataSource = new BindingSource() {DataSource = list};
    Ответ написан
    Комментировать