@saneok44

С# Taks и Invoke почему то блокируется форма?

Всем привет. Столкнулся с весьма странной проблемой. А именно блокировкой формы даже когда используется Invoke. Имеется условно форма с прогресс баром и две таски с вычисления мира. Каждая таска запускается со своей кнопки. Внутри задачи через Invoke вызывается прогресс бар и его счетчик инкрементируется. Условно с первой таски форма не блокируется после клика в любую область все работает как и задумывалось, а вот со второй таски после клика в произвольную область форма вешается но прогресс бар идет дальше до завершения таски и после завершения обрабатывается этот клик как будто то действие встало в очередь. Все классы и методы перепроверил ни что не должно было блокировать форму.
  • Вопрос задан
  • 80 просмотров
Пригласить эксперта
Ответы на вопрос 2
twobomb
@twobomb
Invoke помоему синхронно работает с основным потоком, если вы в Invoke засунули не просто обновление прогресс бара,а какой-то продолжительный процесс то будет блокироваться. Или используйте BeginInvoke или Invoke но обновляйте только прогресс бар через него не более.
Ответ написан
Casper-SC
@Casper-SC
.NET программист
Посмотри как я реализовал класс Analyzer, напиши свой алгоритм по такому же принципу. Внимательно прочитай комментарии в коде класса. Почитай про события в C#. Напиши отдельный класс с алгоритмом, который генерирует события, а уже в форме подпишись на события и обновляй UI. Сообщения из алгоритма отправляй через контекст синхронизации, в алгоритме не дожидайся завершения работы обработчика события (метод Post у контекста синхронизации потоков). Не пиши весь код в методах обработчиках событий форм (окон).

В классе Analyzer
await Task.Delay(250);
просто для имитации долгой работы.

Код ниже слегка отличается от кода по ссылке.
using System;
using System.Threading;
using System.Threading.Tasks;

namespace ProgressBarExample
{
    internal class Analyzer
    {
        private readonly SynchronizationContext _synchronizationContext;

        public Analyzer()
        {
            // Если экземпляр класса будет создан в UI потоке,
            // то здесь будет контекст синхронизации UI потока, иначе пула потоков
            _synchronizationContext = SynchronizationContext.Current ?? new SynchronizationContext();
        }

        public event EventHandler<AnalyzerEventArgs> ProgressChanged;

        public Task<Data> DoWork()
        {
            return Task.Run(async () =>
            {
                for (int i = 0; i < 100; i++)
                {
                    // Имитация долгой работы
                    await Task.Delay(250);
                    // Здесь ты можешь так же как в своём коде вызывать OnProgressChanged
                    // раз в несколько миллисекунд. В форме в UI потоке без Invoke обрабатывать 
                    // событие, выводя те данные, которые ты поместишь в AnalyzerEventArgs
                    OnProgressChanged(new AnalyzerEventArgs("line " + (i + 1), 100));
                }
                return new Data() { Text = "Данные " };
            });
        }

        private void OnProgressChanged(AnalyzerEventArgs args)
        {
            // Перенаправляем выполнение в UI поток не ожидая пока отработает метод обработчик события.
            _synchronizationContext.Post(state =>
            {
                ProgressChanged?.Invoke(this, (AnalyzerEventArgs)state);
            }, args); // args передаётся в переменную state (грубо говоря)
        }
    }
}


namespace ProgressBarExample
{
    public class AnalyzerEventArgs
    {
        public int MaxLines { get; }

        public string CurrentLine { get; }

        public AnalyzerEventArgs(string currentLine, int maxLines)
        {
            CurrentLine = currentLine;
            MaxLines = maxLines;
        }
    }
}


namespace ProgressBarExample
{
    public class Data
    {
        public string Text { get; set; }
    }
}


По ссылке полный код WPF приложения (не важно какой проект, в Windows Forms всё так же будет работать).
Как сделать, чтобы ProgressBar работал во время нагрузки на приложение?
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы