Answer the question
In order to leave comments, you need to log in
How to make the ProgressBar work while the application is under load?
Hello. I have a WPF application:
<Window.Resources>
<Style x:Key="NormalStatusBar" TargetType="DockPanel">
<Setter Property="Background" Value="#FF007ACC" />
</Style>
<Style x:Key="LoadDataStatusBar" TargetType="DockPanel">
<Setter Property="Background" Value="#9333FF" />
</Style>
<Style x:Key="ErrorStatusBar" TargetType="DockPanel">
<Setter Property="Background" Value="#eb4034" />
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="20" />
</Grid.RowDefinitions>
<Menu VerticalAlignment="Top">
<MenuItem Header="File">
<MenuItem
x:Name="LoadDataToDB"
Click="LoadDataToDB_Click"
Header="LoadDataToDB" />
</MenuItem>
</Menu>
<DockPanel x:Name="StatusBar" Grid.Row="1" Style="{StaticResource LoadDataStatusBar}"> <!--Style меняться во время выполнения LoadDataInDB()-->
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock
x:Name="DataStatus"
Grid.Column="0"
Margin="10,0,0,0"
Foreground="White"
Text="Статус данных" />
<DockPanel Grid.Column="1" HorizontalAlignment="Right">
<TextBlock
x:Name="CurrnetLine"
Margin="0,0,5,0"
Foreground="White"
Text="{Binding currentLine}" /> <!--должно меняться во время выполнения LoadDataInDB()-->
<TextBlock
Margin="0,0,5,0"
Foreground="White"
Text="/" />
<TextBlock
x:Name="MaxLines"
Margin="0,0,10,0"
Foreground="White"
Text="{Binding maxLines}" />
</DockPanel>
</Grid>
</DockPanel>
</Grid>
public string maxLines { get; set; }
public string currentLine { get; set; }
Style normalBarStyle;
Style LoadBarStyle;
Style errorBarStyle;
public MainWindow()
{
InitializeComponent();
normalBarStyle = this.FindResource("NormalStatusBar") as Style;
LoadBarStyle = this.FindResource("LoadDataStatusBar") as Style;
errorBarStyle = this.FindResource("ErrorStatusBar") as Style;
StatusBar.Style = normalBarStyle;
DataContext = this;
}
private void LoadDataToDB_Click(object sender, RoutedEventArgs e)
{
StatusBar.Style = LoadBarStyle;
Mouse.OverrideCursor = Cursors.Wait;
Analyzer analyzer = new Analyzer();
analyzer.LoadDataInDB(this);//вызываю метод который делает приложение не активным
Mouse.OverrideCursor = Cursors.Arrow;
StatusBar.Style = normalBarStyle;
}
public event PropertyChangedEventHandler PropertyChanged;
public void ChangeLineData()
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(maxLines)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(currentLine)));
}
if (запрос к бд == true) {
DataBase.ClearAll();
DirectoryInfo info = new DirectoryInfo(@"path\Data\");
DirectoryInfo[] dirs = info.GetDirectories();
for (int r = 0; r < dirs.Length; r++) {
var additionalLines = File.ReadAllLines(@"path\Data\" + dirs[r].Name + @"\
Additional.txt "); ~ 10000строк
var mainLines = File.ReadAllLines(@"pathr\Data\" + dirs[r].Name + @"\
Main.txt "); ~ 18000строк
for (int i = 0; i < mainLines.Length; i++) {
DataMain data = new DataMain(); //обычный класс с переменными
int markCounter = 0; //слова отделяются символом '!'
string word = string.Empty;
for (int j = 0; j < mainLines[i].Length; j++) {
char symbol = mainLines[i][j];
mainWindow.maxLines = mainLines.Length.ToString(); //общие количество линий
mainWindow.currentLine = i.ToString(); //текущая линя
mainWindow.ChangeLineData(); //вызываю метод для смены данных bining полей
if (symbol == '!') { //если символ равен разделителю слов
switch (markCounter) {
case 2: //если второе слово, то заполнятся это:
data.Alpha = Convert.ToInt32(word);
break;
case 1: //и дальше тем же методом
data.Bravo = long.Parse(word);
break;
case 0:
data.Charlie = ConvertToInt(word);
break;
case 5:
data.Delta = ConvertToInt(word);
break;
case 6:
data.Echo = ConvertToInt(word);
break;
case 7:
data.Foxtrot = ConvertToInt(word);
break;
case 10:
data.Golf = ConvertToInt(word);
break;
case 11:
data.Hotel = ConvertToInt(word);
break;
}
word = string.Empty;//очистка переменной
markCounter++;// +1 к счетчику разделителей
} else { //иначе добавляется символ к слову
word += symbol.ToString();
}
}
DataBase.AddMainData(data); // вызов хранимой процедуры с параметрами
}
for (int i = 0; i < additionalLines.Length; i++) {
//тут все тоже самое только в DataAdditional полей в раза 3-4 больше.
}
}
}
Answer the question
In order to leave comments, you need to log in
Made based on your code. In general, you need to write it all a little differently. Passing a reference to classes with algorithms to controls is a very bad idea and immediately forget about this approach.
In this example, if you double-click on the menu item, then two loops will be launched into the thread(s) from the thread pool. You will process it yourself.
In this example, the Analyzer is a separate entity that can notify the outside world about some of its internal events through signals. The event is the same signal, and any number of subscribers can process it. The event can be perceived as pins on the Raspberry Pi board, if you connect something to it, you can somehow react to the signal from the pin, the same thing here.
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 async Task<Data> LoadDataInDB()
{
var result = await Task.Run(async () =>
{
for (int i = 0; i < 100; i++)
{
await Task.Delay(250);
OnProgressChanged(new AnalyzerEventArgs("line " + (i + 1), 100));
}
return new Data() { Text = "Данные " };
});
return result;
}
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; }
}
}
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Input;
namespace ProgressBarExample
{
public partial class MainWindow : Window, INotifyPropertyChanged
{
private readonly Analyzer _analyzer;
private readonly Style _normalBarStyle;
private readonly Style _loadBarStyle;
private readonly Style _errorBarStyle;
private string _maxLines;
private string _currentLine;
public string MaxLines
{
get { return _maxLines; }
set
{
_maxLines = value;
OnPropertyChanged();
}
}
public string CurrentLine
{
get { return _currentLine; }
set
{
_currentLine = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
public MainWindow()
{
InitializeComponent();
_normalBarStyle = FindResource("NormalStatusBar") as Style;
_loadBarStyle = FindResource("LoadDataStatusBar") as Style;
_errorBarStyle = FindResource("ErrorStatusBar") as Style;
_statusBar.Style = _normalBarStyle;
_analyzer = new Analyzer();
_analyzer.ProgressChanged += OnAnalyzerProgressChanged;
}
private void OnAnalyzerProgressChanged(object sender, AnalyzerEventArgs args)
{
// Передавать каждый раз одно и тоже бессмысленно, сделаете сами как нужно
MaxLines = args.MaxLines.ToString();
CurrentLine = args.CurrentLine;
}
private async void LoadDataToDB_Click(object sender, RoutedEventArgs e)
{
_statusBar.Style = _loadBarStyle;
Mouse.OverrideCursor = Cursors.Wait;
try
{
var data = await _analyzer.LoadDataInDB();
MessageBox.Show(data.Text);
}
finally
{
Mouse.OverrideCursor = Cursors.Arrow;
_statusBar.Style = _normalBarStyle;
}
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
<Window
x:Class="ProgressBarExample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:ProgressBarExample"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow"
Width="800"
Height="450"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
mc:Ignorable="d">
<Window.Resources>
<Style x:Key="NormalStatusBar" TargetType="DockPanel">
<Setter Property="Background" Value="#FF007ACC" />
</Style>
<Style x:Key="LoadDataStatusBar" TargetType="DockPanel">
<Setter Property="Background" Value="#9333FF" />
</Style>
<Style x:Key="ErrorStatusBar" TargetType="DockPanel">
<Setter Property="Background" Value="#eb4034" />
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="20" />
</Grid.RowDefinitions>
<Menu VerticalAlignment="Top">
<MenuItem Header="File">
<MenuItem
x:Name="LoadDataToDB"
Click="LoadDataToDB_Click"
Header="LoadDataToDB" />
</MenuItem>
</Menu>
<DockPanel
x:Name="_statusBar"
Grid.Row="1"
Style="{StaticResource LoadDataStatusBar}">
<!-- Style меняться во время выполнения LoadDataInDB() -->
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Column="0"
Margin="10,0,0,0"
Foreground="White"
Text="Статус данных" />
<DockPanel Grid.Column="1" HorizontalAlignment="Right">
<TextBlock
Margin="0,0,5,0"
Foreground="White"
Text="{Binding CurrentLine}" />
<!-- должно меняться во время выполнения LoadDataInDB() -->
<TextBlock
Margin="0,0,5,0"
Foreground="White"
Text="/" />
<TextBlock
Margin="0,0,10,0"
Foreground="White"
Text="{Binding MaxLines}" />
</DockPanel>
</Grid>
</DockPanel>
</Grid>
</Window>
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question