Ответы пользователя по тегу C#
  • Как сделать полупрозрачным контейнер, а его дочерний элемент оставить непрозрачным?

    lam0x86
    @lam0x86
    Можно сделать так:
    <Grid>
      <Подложка Opacity="0.1" />
      <Дочерний_Элемент />
    </Grid>
    Ответ написан
    Комментировать
  • Сравнить два массива, вывести отличия?

    lam0x86
    @lam0x86
    Просто погуглите "C# diff algo".
    Например, вот библиотечка от самого гугла: https://github.com/google/diff-match-patch
    Она правда по умолчанию работает на уровне символов, а не строк, но это можно исправить вот так:
    https://github.com/google/diff-match-patch/wiki/Li...
    Ответ написан
  • Как сделать чтобы уменьшенное изображение окна было вовремя создано?

    lam0x86
    @lam0x86
    Советую почитать про класс TaskbarItemInfo. Там работать с thumbnail-ами гораздо удобнее, чем через WinAPI.
    Ответ написан
    Комментировать
  • Как реализовать ожидание готовности выполнения метода без использования цикла while?

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

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

    lam0x86
    @lam0x86
    Я пока не очень понял смысл приведенного кода. game.Status = "playing" должен выставиться сразу, или сначала нужно послать несколько сообщений пользователям с интервалом в 1 секунду, и уже потом игра переходит в состояние playing? Предположу, что второе.
    Навскидку, вижу несколько ошибок в коде. Во-первых, метод DoWork должен возвращать Task, а не void. Тогда метод StartAsync будет выглядеть так:
    public async Task StartAsync(CancellationToken cancellationToken)
    {
        // Хорошим тоном считается использовать CancellationToken, если он есть. 
        // Иначе задачу невозможно будет отменить.
        await DoWork(cancellationToken); 
    }

    Далее, вы зачем-то отправляете сообщения клиентам в отдельном таске, хотя логичнее было бы сделать это тут же (если моё предположение верно, и нам надо перевести игру в playing только после отправки всех сообщений).
    Ну и как сказали выше, using нужно расширить до конца метода.
    Ответ написан
  • Как прервать выполнение хранимой процедуры при использовании OracleDataReader?

    lam0x86
    @lam0x86
    У OracleDataReader-а есть асинхронные варианты методов. Можно вместо Read вызывать ReadAsync и передавать туда свой CancellationToken.
    Ответ написан
  • Есть ли смысл разрабатывать приложения для Андроид на C#?

    lam0x86
    @lam0x86
    C# активно развивается в данный момент, а .net фрэймворк стал кроссплатформенным, что сулит ему отличное будущее.
    А Java развивается гораздо медленнее и погрязла в бюрократических согласованиях. Поэтому, все новые проекты под Android пишутся на Kotlin`е.

    Суммируя мысли: Джаву учить бессмысленно. Имеет смысл учить Kotlin или C#. Оба языка имеют потенциал. Но только не Джава.
    Ответ написан
    1 комментарий
  • Для написания полноценного телеграм бота на 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#, лучше сразу начинать с него.
    Ответ написан
    Комментировать
  • C# Как зашифровать файл?

    lam0x86
    @lam0x86
    Честно говоря, я не совсем понял, в чём состоит проблема. Если файл не слишком большой, то можно прочитать его в память при помощи File.ReadAllText, затем закодировать содержимое и записать в другой файл. Если файл большой, то можно использовать FileStream - логика немного меняется, но тоже ничего сложного.

    Я немного оптимизировал Ваш код для строк:
    class Crypto2
        {
            private readonly int[] _key;
            private readonly int[] _inversedKey;
    
            public Crypto2(string key)
            {
                var indexPairs = key
                    .Select((chr, idx1) => new { chr, idx1 }) // присваиваем каждому символу индекс
                    .OrderBy(arg => arg.chr) // сортируем по символам
                    .Select((arg, idx2) => new { arg.idx1, idx2 }) // и теперь создаём массив из пар "первоначальный индекс" <=> "отсортированный индекс".
                    .ToArray();
    
                // Генерируем прямой ключ: чем "меньше" символ (в алфавитном порядке), тем меньше его индекс в конечном массиве.
                // "а" => 0, ... , "ь" => 5
                // Получаем: "цезарь" => [4, 1, 2, 0, 3, 5]
                _key = indexPairs
                    .OrderBy(arg => arg.idx1)
                    .Select(arg => arg.idx2)
                    .ToArray();
    
                // Обратная операция для декодирования
                _inversedKey = indexPairs
                    .OrderBy(arg => arg.idx2)
                    .Select(arg => arg.idx1)
                    .ToArray();
            }
    
            public string Encrypt(string message)
            {
                return EncryptDecrypt(message, _key);
            }
    
            public string Decrypt(string message)
            {
                return EncryptDecrypt(message, _inversedKey);
            }
    
            private static string EncryptDecrypt(string message, int[] key)
            {
                var keyLength = key.Length;
                var messageLength = message.Length;
                if (messageLength % keyLength > 0)
                {
                    // Дополняем строку пробелами, если необходимо
                    message = message.PadRight(messageLength + keyLength - messageLength % keyLength, ' ');
                }
    
                // Никогда не используйте конкатенацию строк в цикле (типа result += keyValuePairs[editKey[j]][i].ToString();). Это очень медленно.
                // Для этих целей есть специальный класс StringBuilder.
                // Мы заранее знаем длину конечной строки, поэтому инициализируем StringBuilder правильно.
                var sb = new StringBuilder(messageLength) {Length = message.Length};
    
                for (var i = 0; i < message.Length; i++)
                {
                    // Вычисляем конечный индекс для вставки символа. 
                    // Первая часть выражения "i / keyLength * keyLength" - округление i вниз до ближайшего значения, делящегося на keyLength
                    // Вторая часть "key[i % keyLength]" - вычисление новой позиции символа на основе ключа.
                    var idx = i / keyLength * keyLength + key[i % keyLength];
                    sb[idx] = message[i];
                }
    
                return sb.ToString();
            }
        }


    А вот тот же код для файлов:

    class Crypto3
        {
            private readonly int[] _key;
            private readonly int[] _inversedKey;
    
            public Crypto3(string key)
            {
                var indexPairs = key
                    .Select((chr, idx1) => new {chr, idx1})
                    .OrderBy(arg => arg.chr)
                    .Select((arg, idx2) =>
                        new
                        {
                            arg.idx1, idx2
                        })
                    .ToArray();
    
                _key = indexPairs
                    .OrderBy(arg => arg.idx1)
                    .Select(arg => arg.idx2)
                    .ToArray();
    
                _inversedKey = indexPairs
                    .OrderBy(arg => arg.idx2)
                    .Select(arg => arg.idx1)
                    .ToArray();
            }
    
            public void Encrypt(string sourceFile, string destinationFile)
            {
                EncryptDecrypt(sourceFile, destinationFile, _key);
            }
    
            public void Decrypt(string sourceFile, string destinationFile)
            {
                EncryptDecrypt(sourceFile, destinationFile, _inversedKey);
            }
    
            private static void EncryptDecrypt(string sourceFile, string destinationFile, int[] key)
            {
                var keyLength = key.Length;
                var buffer1 = new byte[keyLength];
                var buffer2 = new byte[keyLength];
                using (var source = new FileStream(sourceFile, FileMode.Open))
                using (var destination = new FileStream(destinationFile, FileMode.OpenOrCreate))
                {
                    while (true)
                    {
                        var read = source.Read(buffer1, 0, keyLength);
                        if (read == 0)
                        {
                            return;
                        }
                        else if (read < keyLength)
                        {
                            for (int i = read; i < keyLength; i++)
                            {
                                buffer1[i] = (byte) ' ';
                            }
                        }
    
                        for (var i = 0; i < keyLength; i++)
                        {
                            var idx = i / keyLength * keyLength + key[i % keyLength];
                            buffer2[idx] = buffer1[i];
                        }
    
                        destination.Write(buffer2, 0, keyLength);
                    }
                }
            }
        }
    Ответ написан
    1 комментарий
  • Как строку форматировать в функцию (C#)?

    lam0x86
    @lam0x86
    Есть два пути:
    1. Сложный - самому написать калькулятор выражений. Если выражения несложные, то такой путь предпочтительный.
    2. Использовать пакет Microsoft.CodeAnalysis.CSharp.Scripting (для .NET Framework 4.6+ или .NET Core 1.1+):
    • Проинсталировать пакет:
      Install-Package Microsoft.CodeAnalysis.CSharp.Scripting

    • Вычислить выражение:
      int result = await CSharpScript.EvaluateAsync<int>("14 - 15");

    Ответ написан
    Комментировать
  • Скрыть область видимости переменной?

    lam0x86
    @lam0x86
    Можно написать Code Analyzer, который будет выдавать ошибку компиляции в случае использовании переменной внутри блока, помеченного каким-либо способом, например специальным комментарием с именами запрещенных переменных:

    int i = 0;
    // HIDE: i
    for(int j=0; j<=N; j++) {
      if(elem[i]==null) { // Ошибка компиляции: использование запрещённой переменной.
      }
    }
    // SHOW: i
    i++; // Нет ошибки.


    или блоком using:
    int i = 0;
    using (CompilerUtils.HideVar(i))
    {
      for(int j=0; j<=N; j++){
        if(elem[i]==null) { // Ошибка компиляции: использование запрещённой переменной
        }
      }
    }
    i++; // OK.


    Сам код HideVar может не делать ничего:
    public static class CompilerUtils
    {
      public static IDisposable HideVar(params object[] vars)
      {
        return <пустая реализация IDisposable>;
      }
    }
    Ответ написан
    Комментировать
  • Как организовать обработку сообщений на сервере?

    lam0x86
    @lam0x86
    Если у вас используется отдельный контейнер для контроллеров, то такое решение возможно, но по факту контейнер может быть заменён обычным Dictionary<Type, IController>.
    Если же вы регистрируете свои контроллеры в общем контейнере - это выглядит странно.

    И в целом, структура класса Message вызывает сомнение. Зачем Encoding и BufferLengthSize? Почему Type имеет тип System.Type, а не System.String?
    Ответ написан
  • Как получить доступ к динамически созданным c помощью datatemplate объектам в xaml?

    lam0x86
    @lam0x86
    Не надо получать доступ к TextBox-ам, это нарушает принцип MVVM (хотя и возможно через хаки типа обхода визуального дерева). К тому же, при режиме
    VirtualizingStackPanel.VirtualizationMode="Recycling"
    (который используется по умолчанию) не всем элементам массива ParameterList будут соответствовать TextBox-ы.

    Предполагается что данные в этих textbox будут меняться и передаваться дальше.

    Вот тут не понял. Что значит передаваться дальше?
    Ответ написан
  • Почему в контроллер не передаются данный?

    lam0x86
    @lam0x86
    Сто лет не занимался ASP.NET, но предположу, что если во фронт-энде написать:
    data: {stat: "Hello"}
    то всё заработает.
    Ответ написан
    5 комментариев
  • Многопоточность 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 ххх
    Ответ написан
  • Почему глобальная переменная видна только из функции где задано значение?

    lam0x86
    @lam0x86
    Лучше переписать этот метод, чтобы он выполнялся асинхронно.
    private async Task<string> jsexec()
    {
      string script = "$('.page_title').text()";
      var response = await chromeBrowser.EvaluateScriptAsync(script);
      if (response.Success && response.Result != null)
      {
        var result = response.Result.ToString();
        MessageBox.Show(result);
        return result;
      }
      else
      {
        return null;
      }
    }
    Ответ написан