Посмотри как я реализовал класс 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 работал во время нагрузки на приложение?