Improve speed stats, UI usability, and settings persistence
Enhanced speed counter with smoothing and elapsed time display. Added folder open buttons to UI and repositioned speed label. Added UpdateSubdirectories to settings for persistence.
This commit is contained in:
parent
c2fd4bf780
commit
6ccbec890a
3 changed files with 103 additions and 28 deletions
|
|
@ -849,6 +849,11 @@ namespace ImageCatalog_2
|
|||
// Atomic counter for processed images — avoids expensive ConcurrentBag.Count enumerations
|
||||
private int _processedAtomic = 0;
|
||||
private System.Threading.Timer? _speedTimer;
|
||||
// Stopwatch used to compute run-wide averages
|
||||
private Stopwatch? _speedWatch;
|
||||
// Recent diffs queue to smooth short-term fluctuations
|
||||
private readonly Queue<int> _recentDiffs = new();
|
||||
private int _recentWindowSize = 5; // average over last 5 samples (~5s)
|
||||
|
||||
private void Test(object parameter)
|
||||
{
|
||||
|
|
@ -907,6 +912,8 @@ namespace ImageCatalog_2
|
|||
_processedAtomic = 0;
|
||||
|
||||
// Start speed timer (sample every second using lightweight atomic reads)
|
||||
_speedWatch = Stopwatch.StartNew();
|
||||
_recentDiffs.Clear();
|
||||
_speedTimer = new System.Threading.Timer(UpdateSpeedCounter, null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1));
|
||||
|
||||
var time = await _imageCreationService.CreaCatalogoParallel(
|
||||
|
|
@ -915,9 +922,28 @@ namespace ImageCatalog_2
|
|||
OnImageProcessed,
|
||||
token);
|
||||
|
||||
SpeedCounter = time;
|
||||
// Compute final averages and show only averages (do not show raw seconds)
|
||||
var finalProcessed = System.Threading.Volatile.Read(ref _processedAtomic);
|
||||
double overallAvg = 0.0;
|
||||
double overallPerMin = 0.0;
|
||||
if (_speedWatch is not null && _speedWatch.Elapsed.TotalSeconds > 0.0)
|
||||
{
|
||||
overallAvg = finalProcessed / _speedWatch.Elapsed.TotalSeconds;
|
||||
overallPerMin = overallAvg * 60.0;
|
||||
}
|
||||
|
||||
// Compute elapsed time as h m s and show final averages (no raw seconds parentheses)
|
||||
var finalElapsed = _speedWatch?.Elapsed ?? TimeSpan.Zero;
|
||||
int fh = (int)finalElapsed.TotalHours;
|
||||
int fm = finalElapsed.Minutes;
|
||||
int fs = finalElapsed.Seconds;
|
||||
|
||||
SpeedCounter = $"{fh}h {fm}m {fs}s{Environment.NewLine}media: {overallAvg:0.00} f/s{Environment.NewLine}media: {overallPerMin:0.00} f/m";
|
||||
|
||||
_speedTimer?.Dispose();
|
||||
_speedTimer = null;
|
||||
_speedWatch?.Stop();
|
||||
_speedWatch = null;
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
|
|
@ -942,12 +968,57 @@ namespace ImageCatalog_2
|
|||
|
||||
private void UpdateSpeedCounter(object? state)
|
||||
{
|
||||
_previousAmount = _currentAmount;
|
||||
// Read the atomic counter without enumerating the ConcurrentBag
|
||||
_currentAmount = System.Threading.Volatile.Read(ref _processedAtomic);
|
||||
int diff = _currentAmount - _previousAmount;
|
||||
// Report files per second (timer runs every 1s)
|
||||
SpeedCounter = $"{diff} f/s";
|
||||
try
|
||||
{
|
||||
_previousAmount = _currentAmount;
|
||||
// Read the atomic counter without enumerating the ConcurrentBag
|
||||
_currentAmount = System.Threading.Volatile.Read(ref _processedAtomic);
|
||||
int diff = _currentAmount - _previousAmount;
|
||||
|
||||
// Protect against negative or spurious diffs
|
||||
if (diff < 0) diff = 0;
|
||||
|
||||
// Maintain a small sliding window of recent diffs to smooth the display
|
||||
lock (_recentDiffs)
|
||||
{
|
||||
_recentDiffs.Enqueue(diff);
|
||||
if (_recentDiffs.Count > _recentWindowSize)
|
||||
_recentDiffs.Dequeue();
|
||||
}
|
||||
|
||||
double avgRecent;
|
||||
lock (_recentDiffs)
|
||||
{
|
||||
avgRecent = _recentDiffs.Count == 0 ? 0.0 : _recentDiffs.Average();
|
||||
}
|
||||
|
||||
// Compute overall average (since start) if we have a stopwatch
|
||||
double overall = 0.0;
|
||||
if (_speedWatch is not null && _speedWatch.Elapsed.TotalSeconds >= 1)
|
||||
{
|
||||
var elapsedSeconds = _speedWatch.Elapsed.TotalSeconds;
|
||||
var total = System.Threading.Volatile.Read(ref _processedAtomic);
|
||||
overall = elapsedSeconds > 0 ? total / elapsedSeconds : 0.0;
|
||||
}
|
||||
|
||||
// Recent per-minute estimate
|
||||
var recentPerMin = avgRecent * 60.0;
|
||||
var overallPerMin = overall * 60.0;
|
||||
|
||||
// Build a two-line display plus elapsed time: first line shows f/s with overall media and elapsed time,
|
||||
// second line shows recent photos per minute (media)
|
||||
var elapsed = _speedWatch?.Elapsed ?? TimeSpan.Zero;
|
||||
int hours = (int)elapsed.TotalHours;
|
||||
int minutes = elapsed.Minutes;
|
||||
int seconds = elapsed.Seconds;
|
||||
var elapsedStr = $"{hours}h {minutes}m {seconds}s";
|
||||
|
||||
SpeedCounter = $"{avgRecent:0.00} f/s (media: {overall:0.00} f/s) - {elapsedStr}{Environment.NewLine}media: {recentPerMin:0.00} f/m";
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Swallow unlikely errors from timing/queue operations but keep UI responsive
|
||||
}
|
||||
}
|
||||
|
||||
private void OnImageProcessed(object? sender, Tuple<string, int> args)
|
||||
|
|
|
|||
42
imagecatalog/MainForm.Designer.cs
generated
42
imagecatalog/MainForm.Designer.cs
generated
|
|
@ -56,6 +56,8 @@ namespace ImageCatalog
|
|||
Label8 = new Label();
|
||||
Label7 = new Label();
|
||||
GroupBox3 = new GroupBox();
|
||||
btnOpenDestFolder = new Button();
|
||||
btnOpenSourceFolder = new Button();
|
||||
chkAggiornaSottodirectory = new CheckBox();
|
||||
_Button3 = new Button();
|
||||
_Button2 = new Button();
|
||||
|
|
@ -181,8 +183,6 @@ namespace ImageCatalog
|
|||
_btnCreaCatalogoAsync = new Button();
|
||||
timer1 = new System.Windows.Forms.Timer(components);
|
||||
dataModelBindingSource1 = new BindingSource(components);
|
||||
btnOpenSourceFolder = new Button();
|
||||
btnOpenDestFolder = new Button();
|
||||
((System.ComponentModel.ISupportInitialize)bindingSource1).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)dataModelBindingSource).BeginInit();
|
||||
TabControl1.SuspendLayout();
|
||||
|
|
@ -245,7 +245,7 @@ namespace ImageCatalog
|
|||
//
|
||||
Label43.AutoSize = true;
|
||||
Label43.DataBindings.Add(new Binding("Text", bindingSource1, "SpeedCounter", true));
|
||||
Label43.Location = new Point(1073, 789);
|
||||
Label43.Location = new Point(1074, 725);
|
||||
Label43.Margin = new Padding(6, 0, 6, 0);
|
||||
Label43.Name = "Label43";
|
||||
Label43.Size = new Size(46, 30);
|
||||
|
|
@ -418,6 +418,24 @@ namespace ImageCatalog
|
|||
GroupBox3.TabStop = false;
|
||||
GroupBox3.Text = "Directory";
|
||||
//
|
||||
// btnOpenDestFolder
|
||||
//
|
||||
btnOpenDestFolder.Location = new Point(939, 97);
|
||||
btnOpenDestFolder.Margin = new Padding(6, 8, 6, 8);
|
||||
btnOpenDestFolder.Name = "btnOpenDestFolder";
|
||||
btnOpenDestFolder.Size = new Size(48, 35);
|
||||
btnOpenDestFolder.TabIndex = 27;
|
||||
btnOpenDestFolder.Text = "Apri";
|
||||
//
|
||||
// btnOpenSourceFolder
|
||||
//
|
||||
btnOpenSourceFolder.Location = new Point(939, 38);
|
||||
btnOpenSourceFolder.Margin = new Padding(6, 8, 6, 8);
|
||||
btnOpenSourceFolder.Name = "btnOpenSourceFolder";
|
||||
btnOpenSourceFolder.Size = new Size(48, 35);
|
||||
btnOpenSourceFolder.TabIndex = 26;
|
||||
btnOpenSourceFolder.Text = "Apri";
|
||||
//
|
||||
// chkAggiornaSottodirectory
|
||||
//
|
||||
chkAggiornaSottodirectory.DataBindings.Add(new Binding("Checked", bindingSource1, "UpdateSubdirectories", true, DataSourceUpdateMode.OnPropertyChanged));
|
||||
|
|
@ -1844,24 +1862,6 @@ namespace ImageCatalog
|
|||
//
|
||||
dataModelBindingSource1.DataSource = typeof(ImageCatalog_2.DataModel);
|
||||
//
|
||||
// btnOpenSourceFolder
|
||||
//
|
||||
btnOpenSourceFolder.Location = new Point(939, 38);
|
||||
btnOpenSourceFolder.Margin = new Padding(6, 8, 6, 8);
|
||||
btnOpenSourceFolder.Name = "btnOpenSourceFolder";
|
||||
btnOpenSourceFolder.Size = new Size(48, 35);
|
||||
btnOpenSourceFolder.TabIndex = 26;
|
||||
btnOpenSourceFolder.Text = "Apri";
|
||||
//
|
||||
// btnOpenDestFolder
|
||||
//
|
||||
btnOpenDestFolder.Location = new Point(939, 97);
|
||||
btnOpenDestFolder.Margin = new Padding(6, 8, 6, 8);
|
||||
btnOpenDestFolder.Name = "btnOpenDestFolder";
|
||||
btnOpenDestFolder.Size = new Size(48, 35);
|
||||
btnOpenDestFolder.TabIndex = 27;
|
||||
btnOpenDestFolder.Text = "Apri";
|
||||
//
|
||||
// MainForm
|
||||
//
|
||||
AutoScaleDimensions = new SizeF(12F, 30F);
|
||||
|
|
|
|||
|
|
@ -177,6 +177,10 @@ namespace ImageCatalog_2.Models
|
|||
[XmlElement("GeneraleRotazioneAutomatica")]
|
||||
public bool AutomaticRotation { get; set; }
|
||||
|
||||
[JsonPropertyName("UpdateSubdirectories")]
|
||||
[XmlElement("DirSottoDirectory")]
|
||||
public bool UpdateSubdirectories { get; set; }
|
||||
|
||||
[JsonPropertyName("AddRaceTime")]
|
||||
[XmlElement("TempoGara")]
|
||||
public bool AddRaceTime { get; set; }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue