Sista posten i denna tråd verkar ha "löst" samma problem.
Min gissning här är att denna lösning mest bara gör att det fel du nu ser blir mindre sannolikt då man ökar tiden från där filen kan släppas till dess att den faktiskt släps. Det är dock inte helt omöjligt att detta faktiskt är något som slutgiltigen löser problemet, enda sättet att reda ut det helt är att reda ut exakt vad som anropas från att man sätter IsEnabled till false till dessa att följande sats körs. Under denna tid befinner man sig i komponenten så den har ju teoretiskt sett möjlighet att utföra "rätt sak" t.ex. efter att IsEnabledChanged returnerar och "upptäcker" att Source är null.
Om vi antar att sannolikheten att filen är låst signifikant minskar om man går omvägen via IsEnabledChanged eventet men att det inte är en korrekt lösning, vad kan det bero på? En hyfsat kvalificerad gissning är att man låter en dtor eller motsvarande (något internt kan ju även använda IDisposable, MediaElement verkar inte implementera detta). Så en väg runt detta problem att man nu inte kan räkna med att filen släps efter att Source sätts till null (att sätta Source till null verkar i alla fall vara ett krav för att detta ska ha någon chans att fungera).
Om mitt spekulerande är rätt så, utan att överhuvudtaget ha testat, borde detta vara en väg runt problemet som också undviker alla race-conditions:
mainVideo.Stop();
mainVideo.Clear();
mainVideo.Source = null;
// Tvinga fram en GC av alla generationer
System.GC.Collect();
// Nu finns ändå en del race, t.ex. kan GC redan köras på någon annan tråd
// eller anropet ovan kanske lägger ut jobbet på en annan tråd. Måste då
// se till att denna tråd väntar till GC kört klart
System.GC.WaitForPendingFinalizers();
// om jag gissat rätt om problemet borde du kunna radera filen här