• Как приостановить или убить дочерний поток в C#?

    @mayorovp
    Для проверки на завершение внутри потока хорошо использовать ManualResetEvent, на нем же и ожидая:

    private void DoWork()
            {
                do
                {
                    Console.WriteLine("SomeWork");
                } while (!closeEvent.WaitOne(1000));
            }


    Ну я для того, чтобы дождаться завершения потока, существует метод Join
    Ответ написан
  • Как обработать огромный текстовый файл?

    lam0x86
    @lam0x86
    Если строки короткие, то, в принципе, подойдёт такое решение:
    var secondFileLines = new HashSet<string>(File.ReadLines("<файл2>"));
    using (var writer = new StreamWriter("<файл3>"))
    {
        foreach (var line in File.ReadLines("<файл1>"))
        {
            if (!secondFileLines.Contains(line))
            {
                writer.WriteLine(line);
            }
        }
    }


    Если длина строк неограничена, то могут возникнуть проблемы с расходом памяти. В этом случае, всё сильно усложняется. Вам, вероятно, придётся хранить набор хэш-кодов строк из второго файла и сравнивать с хэш-кодом каждой строки из первого. Но тут могут возникнуть ложно-положительные срабатывания, если у разных строк хэши будут совпадать. В этом случае, необходимо будет сравнивать строки посимвольно. Это при идеальной реализации. Впрочем, вероятность совпадения хэшей - 1/2^32. Ну, и надо умножить на 70 миллионов. Если задача позволяет добавить пару лишних строк в результирующий файл, я бы так и поступил.
    Можно немного улучшить алгоритм с хэшами: если, например, использовать 256-битную хэш-функцию, а не стандартную (GetHashCode), можно снизить вероятность ложного срабатывания до 1e-77 (в случае использования SHA1). Думаю, такой мизерной вероятности будет достаточно, чтобы считать задачу решённой. Правда, придётся немного усложнить алгоритм сравнения хэшей - придётся сравнивать массивы.
    Ответ написан
    3 комментария
  • Как обработать огромный текстовый файл?

    @mikhail_404
    Используйте хэширование для данной задачи.
    Ответ написан
    Комментировать
  • Как обработать огромный текстовый файл?

    @vilgeforce
    Раздолбай и программист
    Решение "в лоб" вас по скорости уже не устраивает? Предполагаю, что оно решит задачу за минуты.
    Ответ написан
  • Как правильно информировать о процессе выполнения задачи?

    lam0x86
    @lam0x86
    Пробовал через класс Progress, но тут мне не понравилось плодить большое кол во классов через
    Progress.Report(new MyReport{...});

    Ничего страшного в этом нет - эти объекты на самом деле тут же умирают, не покидая первого поколения GC.
    Тут другой вопрос более важен: класс Progress устроен так, что маршаллит все репорты в SynchronizationContext, в котором он был создан. В случае с WinForms - это контекст UI-потока. Если ваш Task слишком часто будет вызывать метод Report, это может негативно сказаться на UI-потоке, т.к. он будет забит репортами, каждый из которых он должен обработать. Более того, поскольку маршаллинг в классе Progress асинхронный, есть вероятность, что задача будет выполнена до того, как на UI-потоке обработаются все репорты. Получется запаздывание прогресс-бара от реального прогресса (и вот тут как раз возникает вероятность перехода репортов в Gen1 и Gen2).

    Я бы написал свою реализацию класса Progress, которая использует таймер, периодически опрашивающий последнее обновление прогресса. Так сделано в большинстве систем, где обновление может происходить часто, например, при копировании множества файлов. Примерно так:

    public interface IProgressInfo
        {
            bool IsCompleted { get; }
        }
    
        public class ProgressInfo : IProgressInfo
        {
            public ProgressInfo(double completedPercentage, string progressStatusText)
            {
                CompletedPercentage = completedPercentage;
                ProgressStatusText = progressStatusText;
            }
    
            public double CompletedPercentage { get; private set; }
    
            public string ProgressStatusText { get; private set; }
    
            public bool IsCompleted
            {
                get { return CompletedPercentage >= 1; }
            }
        }
    
        public class Progress<T> : IProgress<T> where T : class, IProgressInfo
        {
            private T _previousProgressInfo;
            private volatile T _progressInfo;
            private readonly Action<T> _updateProgressAction;
            private readonly Timer _timer;
            private readonly SynchronizationContext _synchronizationContext;
    
            public Progress(TimeSpan pollingInterval, Action<T> updateProgressAction)
            {
                _synchronizationContext = SynchronizationContext.Current ?? new SynchronizationContext();
                _updateProgressAction = updateProgressAction;
                _timer = new Timer(TimerCallback, null, pollingInterval, pollingInterval);
            }
    
            private void TimerCallback(object state)
            {
                ProcessUpdate();
            }
    
            private void ProcessUpdate()
            {
                var progressInfo = _progressInfo;
                if (_previousProgressInfo != progressInfo)
                {
                    _synchronizationContext.Send(state => _updateProgressAction((T) state), progressInfo);
                }
                _previousProgressInfo = progressInfo;
            }
    
            public void Report(T value)
            {
                _progressInfo = value;
                if (value.IsCompleted)
                {
                    _timer.Dispose();
                    ProcessUpdate();
                }
            }
        }


    Использовать его можно примерно так:

    var workClass = new WorkClass();
    
                var list = Enumerable.Range(1, 1000).Select(i => i.ToString()).ToArray();
                var progress = new Progress<ProgressInfo>(TimeSpan.FromMilliseconds(100), UpdateProgressAction);
    
                await workClass.LongMethod(list, progress);


    где:

    private void UpdateProgressAction(ProgressInfo obj)
            {
                ProgressBar.Value = obj.CompletedPercentage;
                OperationStatus.Text = obj.ProgressStatusText;
                ProgressBarPercentage.Text = string.Format("{0:P}", obj.CompletedPercentage);
            }
    
    internal class WorkClass
        {
            public async Task LongMethod(IReadOnlyList<string> something, IProgress<ProgressInfo> progress)
            {
                await Task.Factory.StartNew(() =>
                {
                    var count = something.Count;
                    for (int i = 0; i < count; i++)
                    {
                        var element = something[i];
                        Thread.Sleep(5);
                        progress.Report(new ProgressInfo((double)(i + 1) / count, element));
                    }
                });
            }
        }
    Ответ написан
    3 комментария
  • Возможна ли авторизация OAuth 2.0 без браузера?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Поставщик может позволить принимать у пользователя логин и пароль и преобразовывать их в маркер доступа (accsss token). Но, как правило в целях безопасности, никто не дает такой возможности.

    Попробуйте: если grant_type будет password, то данные пользователя можно передавать в параметрах username и password при получении маркера доступа. Либо использовать grant_type равный client_credentials, тогда данные пользователя должны передаваться в HTTP заголовке Authorization (при использовании HTTPS это более безопасный способ, чем password).

    Например, если бы Facebook позволял это делать, то запрос маркера доступа мог бы быть таким:
    https://graph.facebook.com/oauth/access_token?client_id=123&client_secret=abc&
    grant_type=password&username=pupkin&password=000


    В моей библиотеке пока нет возможности менять grant_type снаружи, но можно внутри поменять. Например, InstagramClient.cs, в конструкторе указать GrantType:

    base.GrantType = GrantType.ClientCredentials;

    И далее использовать клиент:

    var client = new InstagramClient
    (
      "9fcad1f7740b4b66ba9a0357eb9b7dda", 
      "3f04cbf48f194739a10d4911c93dcece"
    );
    client.ReturnUrl = "http://oauthproxy.nemiro.net/";
    client.Username = "aleksey";
    client.Password = "Frif#dser#23dssd@Dsdfjjfsi";
    var accessToken = client.AccessToken;

    И сервер ответит:
    {"code": 400, "error_type": "OAuthException", "error_message": "Invalid grant_type"}

    Плохой пример :P

    А вот Facebook, на удивление, вернул маркер доступа:
    var client = new FacebookClient("1435890426686808", "c6057dfae399beee9e8dc46a4182e8fd");
    client.Username = "aleksey";
    client.Password = "a6lGmDZsCb1SuHsIQw89ZqK9";
    var accessToken = client.AccessToken;

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

    @mayorovp
    Нет, Razor Engine сюда не подойдет, потому что оно заточено под вывод html. Но вы можете использовать T4 Text Templates
    Ответ написан
    5 комментариев
  • Есть ли какой то шаблонизатор для C#?

    Deerenaros
    @Deerenaros
    Программист, математик, задрот и даже чуть инженер
    Этот велосипед пишется на раз-два.
    Ответ написан
    2 комментария
  • Правильно ли понимаю полиморфизм?

    AlexanderByndyu
    @AlexanderByndyu
    IT-архитектор, эксперт в Agile&Lean
    Основаные цели при использовании полиморфизма:
    • уменьшение дублирования в коде
    • создание более "гибкого" кода


    Суть в том, что за счет абстракции вы можете передавать разные объекты в одни и те же методы, при этом вам будет не важно какой конкретно объект пришел в метод.

    Приведу пример. Представьте, что у вас есть автомойка - класс Автомойка - которая может работать только для желтой Лады Калина. Другие автомобили в ней не могут быть помыты. В классе есть метод ПомытьЖелтуюЛадуКалину(ЖелтаяЛадаКалина автомобиль). Т.е. есть конкретный метод, который принимает конкретный тип автомобиля.

    В какой-то момент вы понимаете, что могли бы мыть и черные Волги. Вы строите еще один вход для черной Волги, т.е создаете в классе еще один метод ПомытьЧернуюВолгу(ЧернаяВолга автомобиль). Теперь ваш класс Автомойки расширил свои возможности.

    Вы будете добавлять новый метод каждый раз, когда будет появляться новый тип автомобиля, который вы сможете мыть. Самое главное, что каждый из этих методов будет делать практически одно и тоже. Тут у нас 2 проблемы:
    1. дублирование в методах Помыть*
    2. зависимость нашего класса Автомойка от внешнего контекста, где появляются новые типы автомобилей. При появлении нового автомобиля нам приходится модифицировать класс Автомойки (нарушение принципа blog.byndyu.ru/2009/10/blog-post_14.html)


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

    Получаем:
    класс Автомобиль
        свойство Высота
        свойство Ширина
        свойство ТипКузова
    
    класс Автомойка
        метод Помыть(Автомобиль автомобиль)
            настроитьМойкуПоВысоте(автомобиль.Высота)
            настроитьМойкуПоШирине(автомобиль.Ширина)
            настроитьМойкуПоТипуКузова(автомобиль.ТипКузова)
            начатьМойку()


    Теперь сколько бы разных автомобилей не добавлялось в систему наш класс Автомойка не будет меняться. Мы убрали дублирование и сделали наш класс более устойчивым к изменениям во внешней среде. У класс Автомобиль может быть наследник ЖелтаяЛадаКалина и у нее будут свойства/методы базового класса. Т.к. метод Помыть работает с абстракцией, то он будет вызывать полиморфные свойства/методы, ничего не зная о конкретной реализации и иерархии наследования, которая лежит под классом Автомобиль.

    При проектировании классов надо обращать внимание еще на один принцип blog.byndyu.ru/2009/10/blog-post_29.html, тогда дизайн вашей системы будет еще более гибким.
    Ответ написан
    2 комментария