stride3d/stride · error · NotImplementedException
GlobalMutex.Wait() is implemented only for…
Error message
GlobalMutex.Wait() is implemented only for millisecondsTimeout 0 or -1
What it means
FileLock.Wait only supports millisecondsTimeout of 0 (single try) or -1 (infinite wait) because it maps directly onto GlobalMutex.Wait semantics. Any other timeout throws NotImplementedException from the Wait method (also reachable via TryLock).
Solutions
- Use 0 for a single non-blocking attempt and poll in your own loop with Thread.Sleep
- Use -1 to block indefinitely until the lock is acquired
- Wrap the call site with your own deadline logic around repeated 0-timeout attempts
- Check library version/upstream for bounded-timeout support before using other values
Example fix
// before var l = FileLock.Wait(name, 5000); // after var l = FileLock.Wait(name, -1); // or poll with 0 in your own loop
Defensive patterns
Strategy: try-catch
Validate before calling
if (timeout != 0 && timeout != -1)
throw new InvalidOperationException("FileLock.Wait only supports 0 or -1"); Try / catch
try { l = FileLock.Wait(name, 0); }
catch (NotImplementedException) { /* fall back to manual polling loop */ } Prevention
- Only use 0 or -1 timeouts
- Implement bounded waits with your own poll loop
- Document this API limitation at call sites
When it happens
Trigger: Calling FileLock.Wait(name, timeout) with any value other than 0 or -1, e.g. Wait("mylock", 5000). Also via TryLock if it forwards a non-{0,-1} timeout.
Common situations: Developers assuming a standard bounded-timeout locking API; migrating from Mutex.WaitOne(TimeSpan) style code; adding retry loops with finite timeouts.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Could not start install package process
- Aynchronous lock can only be acquired from a micro-thread…
- Trying to enter a lock that has already been entered
- Trying to lock while another thread owns the lock.
- This operation is already in progress
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/52bc84c659a8c4d7.
Report an issue: GitHub.
Appendix: source
Thrown at sources/core/Stride.Core.Design/Windows/FileLock.cs:87
/// <summary>
/// Tries to take ownership of the file lock within a given delay.
/// </summary>
/// <param name="name">A unique name identifying the file lock.</param>
/// <param name="millisecondsTimeout">The maximum delay to wait before returning, in milliseconds.</param>
/// <returns>A new instance of <see cref="FileLock"/> if the ownership could be taken, <c>null</c> otherwise.</returns>
/// <remarks>
/// The returned <see cref="FileLock"/> must be disposed to release the file lock.
/// Calling this method with 0 for <see paramref="millisecondsTimeout"/> is equivalent to call <see cref="TryLock"/>.
/// Calling this method with a negative value for <see paramref="millisecondsTimeout"/> is equivalent to call <see cref="Wait(string)"/>.
/// </remarks>
public static FileLock? Wait(string name, int millisecondsTimeout)
{
var fileLock = BuildFileLock(name);
try
{
if (millisecondsTimeout != 0 && millisecondsTimeout != -1)
throw new NotImplementedException("GlobalMutex.Wait() is implemented only for millisecondsTimeout 0 or -1");
bool hasHandle = NativeLockFile.TryLockFile(fileLock, 0, uint.MaxValue, true, millisecondsTimeout == 0);
return hasHandle ? new FileLock(fileLock) : null;
}
catch (AbandonedMutexException)
{
return new FileLock(fileLock);
}
}
private static FileStream BuildFileLock(string name)
{
// We open with FileShare.ReadWrite mode so that we can implement `Wait`.
return new FileStream(name, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite);
}
}
View on GitHub (pinned to 96fad776d2)