dotnet/wpf · error · ArgumentOutOfRangeException

throw new ArgumentOutOfRangeException(nameof(timeout));

Error message

throw new ArgumentOutOfRangeException(nameof(timeout));

What it means

D3DImage.TryLock(Duration timeout) attempts to acquire the render lock without blocking indefinitely, so a Duration.Automatic timeout is meaningless and rejected: it throws ArgumentOutOfRangeException for parameter 'timeout'. Only finite durations and Duration.Forever are acceptable.

Solutions

  1. Pass a concrete timeout, e.g. TryLock(TimeSpan.FromMilliseconds(50)) or TryLock(Duration.Forever) for blocking behavior identical to Lock().
  2. Before calling, check `duration != Duration.Automatic` and substitute a real duration.
  3. If you need a 'best effort, no wait' lock, use a very small finite duration such as Duration.Zero or TimeSpan.Zero.

Example fix

// before
Duration d = new Duration(); // Automatic
d3dImage.TryLock(d); // ArgumentOutOfRangeException

// after
var d = TimeSpan.FromMilliseconds(50);
if (d3dImage.TryLock(d)) { try { /* render */ } finally { d3dImage.Unlock(); } }
Defensive patterns

Strategy: validation

Validate before calling

if (duration == Duration.Automatic)
    duration = Duration.Forever; // or a concrete TimeSpan
bool got = d3dImage.TryLock(duration);

Try / catch

try { return d3dImage.TryLock(timeout); }
catch (ArgumentOutOfRangeException ex) when (ex.ParamName == "timeout")
{
    return d3dImage.TryLock(TimeSpan.FromMilliseconds(50));
}

Prevention

When it happens

Trigger: Calling TryLock(new Duration()) (default Duration == Automatic); passing Duration.Automatic explicitly (e.g. reusing a Duration taken from an animation); constructing a Duration from a TimeSpan that was never set or via a default struct.

Common situations: Copying Duration values from animation timelines (where Automatic is legal) into TryLock; default-initialized Duration fields; timing code that computes a Duration lazily and never assigns it.

Understand the failure class

Background: "invalid duration" / "failed to parse duration": why your timeout, interval, or TTL string is rejected and which formats each library accepts — this error's family across 32 libraries.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/f6998b388df74323. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/InterOp/D3DImage.cs:237

        /// </summary>
        public void Lock()
        {
            WritePreamble();

            LockImpl(Duration.Forever);
        }

        /// <summary>
        ///     Trys to lock the D3DImage but gives up once duration expires. Returns true
        ///     if the lock was obtained. See Lock for more details.
        /// </summary>
        public bool TryLock(Duration timeout)
        {
            WritePreamble();

            if (timeout == Duration.Automatic)
            {
                throw new ArgumentOutOfRangeException(nameof(timeout));
            }

            return LockImpl(timeout);
        }

        /// <summary>
        ///     Unlocks the D3DImage
        ///
        ///     Can only be called while locked.
        ///
        ///     If you have dirtied the image with AddDirtyRect, Unlocking will trigger us to
        ///     copy the dirty regions from the back buffer to the front buffer. While this is
        ///     taking place, Lock will block. To avoid locking indefinitely, use TryLock.
        /// </summary>
        public void Unlock()
        {
            WritePreamble();
            

View on GitHub (pinned to 81131a70a4)