Make local sync re-entrancy guard atomic
Der Schutz gegen gleichzeitige Syncs (manuell vs. Auto-Sync-Timer) war ein nicht-atomares pruefen-und-setzen auf einem volatile bool. Zwischen Pruefung und Setzen konnten ein UI-Klick und der Timer-Thread beide durchrutschen und zwei Syncs gleichzeitig starten. Jetzt per Interlocked.CompareExchange atomar. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -38,6 +38,10 @@ Versionsschema ist `x.x.x.x` (siehe `release.sh`).
|
|||||||
|
|
||||||
### Geaendert
|
### Geaendert
|
||||||
|
|
||||||
|
- **Doppelte Syncs verhindert (lokal).** Der Schutz gegen gleichzeitig laufende
|
||||||
|
Syncs (manuell + Auto-Sync-Timer) ist jetzt atomar (`Interlocked`) statt eines
|
||||||
|
nicht-atomaren `volatile bool`, bei dem beide in einem Zeitfenster
|
||||||
|
durchrutschen konnten.
|
||||||
- **Ein-Richtungs-Modi sind jetzt echtes "Ersetzen".** Outlook->Starface macht
|
- **Ein-Richtungs-Modi sind jetzt echtes "Ersetzen".** Outlook->Starface macht
|
||||||
das Starface-Adressbuch zu einer exakten Kopie von Outlook: Kontakte, die nur
|
das Starface-Adressbuch zu einer exakten Kopie von Outlook: Kontakte, die nur
|
||||||
in Starface existieren (kein Pendant in Outlook), werden geloescht.
|
in Starface existieren (kein Pendant in Outlook), werden geloescht.
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Timers;
|
using System.Timers;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
@@ -22,7 +23,9 @@ namespace StarfaceOutlookSync.UI
|
|||||||
private StatusStrip _statusBar;
|
private StatusStrip _statusBar;
|
||||||
private ToolStripStatusLabel _statusLabel;
|
private ToolStripStatusLabel _statusLabel;
|
||||||
private Timer _autoSyncTimer;
|
private Timer _autoSyncTimer;
|
||||||
private volatile bool _syncRunning = false;
|
// 0 = frei, 1 = Sync laeuft. Per Interlocked atomar geschaltet, damit
|
||||||
|
// ein manueller Sync und der Auto-Sync-Timer nicht gleichzeitig starten.
|
||||||
|
private int _syncRunning = 0;
|
||||||
|
|
||||||
public MainForm()
|
public MainForm()
|
||||||
{
|
{
|
||||||
@@ -337,13 +340,14 @@ namespace StarfaceOutlookSync.UI
|
|||||||
|
|
||||||
private async Task RunSync(SyncProfile profile)
|
private async Task RunSync(SyncProfile profile)
|
||||||
{
|
{
|
||||||
if (_syncRunning)
|
// Atomar pruefen-und-setzen: verhindert, dass manueller Sync und
|
||||||
|
// Auto-Sync-Timer gleichzeitig denselben/einen Sync starten.
|
||||||
|
if (Interlocked.CompareExchange(ref _syncRunning, 1, 0) != 0)
|
||||||
{
|
{
|
||||||
SetStatus("Sync laeuft bereits, bitte warten...");
|
SetStatus("Sync laeuft bereits, bitte warten...");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_syncRunning = true;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
SetStatus($"Synchronisiere '{profile.Name}'...");
|
SetStatus($"Synchronisiere '{profile.Name}'...");
|
||||||
@@ -368,7 +372,7 @@ namespace StarfaceOutlookSync.UI
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
_syncRunning = false;
|
Interlocked.Exchange(ref _syncRunning, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user