Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7888551
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 3, 20262026-06-03T05:51:37+00:00 2026-06-03T05:51:37+00:00

General purpose I am developing a .NET user control that can be used for

  • 0

General purpose

I am developing a .NET user control that can be used for multipurpose graphics rendering using Direct2D. This control is based on the ID2D1HwndRenderTarget interface with a ID2D1BitmapRenderTarget back-buffer/double-buffer.

Background

I have written a wrapper using C++/CLI that exposes a set of managed wrapper objects for Direct2D, and I have a designed a Singleton resource manager for Direct2D bitmaps that code can send to the binary data to, and get a resource key back from, which code can then pass in a message to the user control to render a bitmap.

Usage so far

I have been able to load bitmaps, JPEGs, custom imaging formats and the like and send them to the Direct2D render control all with no issue. I’ve written a custom video decoder that could load frames from a 15-fps video (decoding in a background thread) and render them from events raised by a Win32 multimedia timer, no problem.

Issue

My issue is that when I attempted to expand out from a single multimedia format into something more flexible (specifically connecting to LibAV/ffmpeg), the Direct2D render control starts to crash display drivers. This does not happen when frames are rendered sequentially (using a button to render the next frame, rather than a timer). It also does not happen straightaway. It also does not happen when I block inside the Win32 timer callback, but does when I use a Mutex to raise a thread that will free the timer callback up and let the interim thread instruct the control to render.

Symptoms

If I start a timer and attach to its elapsed event methods that will cause the next render, it will typically play fine for around 2-20 seconds. Using smaller video, I can get longer playback before the issue starts. If I play back 1080p video, I can get the crash usually within 5 seconds without contest. Playback will start fine, maybe have a hiccup here or there before catching up.

  • Eventually, I will start to see flickering, as if the background color is rendered but the frame is not. Additional frames may or may not later render, but this is very short-lived.
  • After the flicker, if I stop the timer quickly enough there will be no crash.
  • If I do not stop in time:
    • If I’m lucky (maybe 10% of the time), frames will stop rendering, be stuck on one frame until I resize the control, at which point only black is drawn to the entire control. (I’ve read that this may indicate a lost device context for DirectX rendering, but have not seen much more.)
    • If I’m unlucky, the display driver will crash, Windows recovers and restarts the driver, after which point the EndDraw will finally tell me that an error has occurred and return D2DERR_RECREATE_TARGET.
    • If I am really unlucky, the display will start to look like a kaleidoscope and I’ll have to power off my machine, and I just wasted 5 minutes booting, logging on, loading Visual Studio and my solution, loading the video and lost all my debugging data.

I want to think that there is some sort of race condition that I am missing, but every time I run through the rendering code, it appears that it should be properly locked.

Render Control’s Code

using System;
using System.Drawing;
using System.Windows.Forms;

using Direct2D = Bardez.Projects.DirectX.Direct2D;
using ExternalPixelEnums = Bardez.Projects.FileFormats.MediaBase.Video.Pixels.Enums;
using Bardez.Projects.DirectX.Direct2D;
using Bardez.Projects.FileFormats.MediaBase.Video;
using Bardez.Projects.FileFormats.MediaBase.Video.Enums;
using Bardez.Projects.Win32;

namespace Bardez.Projects.Output.Visual
{
    /// <summary>Represents a rendering target for Direct2D.</summary>
    /// <remarks>
    ///     To use this control, an external component will need to supply bitmap data. This does not need to be a GDI+ Bitmap class.
    ///     However, the container for this control will need to push data into this control.
    ///     So, in the case of a movie player, we'd see the following model:
    ///         * decompress a frame.
    ///         * push frame to control
    ///         * invoke Invalidate
    ///             * control will render the bitmap
    ///         * sleep just a little bit
    ///         * go back to first step
    /// </remarks>
    public class Direct2dRenderControl : VisualRenderControl
    {
        /*
        *   Locking orientation:
        *       There are two rendering targets: a GDI display and a bitmap back buffer.
        *       There are 5 'real' locking operations:
        *           Rendering to the GDI display (OnPaint)
        *           Rendering to the back buffer (DrawBitmapToBuffer, DiscardCurrentBuffer)
        *           Setting the current displayed frame (SetRenderFrame)
        *           Resource Freeing (FreeFrameResource)
        *           Resizing (OnResize)
        *
        *       Briefly, the overarching effects of these five are:
        *           Rendering
        *               Utilizes the buffer and the display
        *           Back Buffer
        *               Utilizes the buffer and if mid-render could affect this display
        *           Set Frame
        *               Sets the buffer's displayed image
        *           Resource Freeing
        *               Affects the buffer if a resource is refernced
        *           Resizing
        *               Resizes the render control and the bitmap, uses the frame set by set
        *
        *       Locking plan:
        *           Resize should block set, free and back buffer
        *           Render should block back buffer, control
        *           Set frame should block resize and back buffer
        *           Free should block back buffer,
        *           Back buffer should block rendering, setting, resizing, freeing
        *
        *       Basically, lock everything at the process level, and not at the access level.
        */

        #region Fields
        /// <summary>Represents a Win32 HWND render target for Direct2D</summary>
        private ControlRenderTarget ctrlRenderTarget;

        /// <summary>Represents a drawing buffer</summary>
        private BitmapRenderTarget bmpRenderTarget;

        /// <summary>Represents a drawing buffer, used solely to create bitmaps</summary>
        private BitmapRenderTarget resourceBmpRenderTarget;

        /// <summary>Represents a buffer drawing command lock</summary>
        private Object controlBufferLock;

        /// <summary>Represents a paint/render drawing command lock</summary>
        private Object controlPaintRenderLock;

        /// <summary>Locking object reference for resource management (memory bitmaps, etc.)</summary>
        private Object resourceLock;

        /// <summary>Represents the key to accessing the currently set key</summary>
        protected Int32 currentFrameKey;
        #endregion


        #region Properties
        /// <summary>Indicates whether there is a frame set for this control</summary>
        protected Boolean HasFrameSet
        {
            get { return currentFrameKey > -1; }
        }

        /// <summary>Exposes a wrapper for the bitmap render target</summary>
        protected BitmapRenderTarget BmpRenderTarget
        {
            get { return this.bmpRenderTarget; }
            set
            {
                lock (this.controlBufferLock)
                {
                    if (this.bmpRenderTarget != null)
                        this.bmpRenderTarget.Dispose();

                    this.bmpRenderTarget = value;
                }
            }
        }

        /// <summary>Exposes a wrapper for the bitmap render target</summary>
        protected BitmapRenderTarget ResourceBmpRenderTarget
        {
            get { return this.resourceBmpRenderTarget; }
            set
            {
                lock (this.resourceLock)
                {
                    if (this.resourceBmpRenderTarget != null)
                        this.resourceBmpRenderTarget.Dispose();

                    this.resourceBmpRenderTarget = value;
                }
            }
        }

        /// <summary>Represents a Win32 HWND render target for Direct2D</summary>
        protected ControlRenderTarget CtrlRenderTarget
        {
            get { return this.ctrlRenderTarget; }
            set
            {
                lock (this.controlPaintRenderLock)
                {
                    if (this.ctrlRenderTarget != null)
                        this.ctrlRenderTarget.Dispose();

                    this.ctrlRenderTarget = value;
                }
            }
        }
        #endregion


        #region Construction
        /// <summary>Default constructor</summary>
        public Direct2dRenderControl() : base()
        {
            this.controlBufferLock = new Object();
            this.controlPaintRenderLock = new Object();
            this.resourceLock = new Object();

            this.currentFrameKey = -1;
            this.InitializeControlDirect2D();
        }

        /// <summary>Initializes the Direct2D</summary>
        protected void InitializeControlDirect2D()
        {
            //disable Windows background draw
            this.SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);

            // Build options on the Control render target
            PixelFormat format = new PixelFormat(DXGI_ChannelFormat.FORMAT_B8G8R8A8_UNORM, AlphaMode.Unknown);  //32-bit color, pure alpha
            DpiResolution res = Direct2dResourceManager.Instance.Factory.GetDesktopDpi();
            RenderTargetProperties rtProp = new RenderTargetProperties(RenderTargetType.Default, format, res, RenderTargetUsage.GdiCompatible, DirectXVersion.DirectX9);

            //Build out control render target properties
            HwndRenderTargetProperties hwndProp = new HwndRenderTargetProperties(this.Handle, new SizeU(this.Size), PresentationOptions.RetainContents);

            lock (this.controlPaintRenderLock)
            {
                // populate the Control rendering target
                ResultCode result = Direct2dResourceManager.Instance.Factory.CreateHwndRenderTarget(rtProp, hwndProp, out this.ctrlRenderTarget);

                lock (this.controlBufferLock)
                {
                    // create a bitmap rendering targets
                    this.CtrlRenderTarget.CreateCompatibleRenderTarget(out this.bmpRenderTarget);

                    lock (this.resourceLock)
                        this.CtrlRenderTarget.CreateCompatibleRenderTarget(out this.resourceBmpRenderTarget);
                }
            }
        }
        #endregion


        #region Destruction
        /// <summary>Disposal code; releases unmanaged resources</summary>
        /// <param name="disposing">True indicates to dispose managed resources</param>
        protected override void Dispose(Boolean disposing)
        {
            this.ResourceBmpRenderTarget = null;    //property disposes
            this.BmpRenderTarget = null;            //property disposes
            this.CtrlRenderTarget = null;           //property disposes
            base.Dispose(disposing);
        }

        /// <summary>Disposal</summary>
        ~Direct2dRenderControl()
        {
            this.Dispose();
        }
        #endregion


        #region Event Raising
        /// <summary>Draws the output, then raises the paint event</summary>
        /// <param name="e">Painting Event arguments</param>
        protected override void OnPaint(PaintEventArgs e)
        {
            lock (this.controlPaintRenderLock)
            {
                lock (this.controlBufferLock)
                {
                    this.SuspendLayout();

                    this.OnPaintBackground(e);

                    Direct2D.Bitmap bmp;
                    ResultCode result;

                    result = this.BmpRenderTarget.GetBitmap(out bmp);

                    Direct2D.RectangleF rect = new Direct2D.RectangleF(e.ClipRectangle);

                    this.CtrlRenderTarget.BeginDraw();

                    this.CtrlRenderTarget.DrawBitmap(bmp, rect, 1.0F, BitmapInterpolationMode.Linear, rect);

                    result = this.CtrlRenderTarget.EndDraw();

                    bmp.Dispose();

                    if (result != ResultCode.Success_OK)
                        throw new ApplicationException(String.Format("Error encountered during draw: '{0}'", result.ToString()));

                    base.OnPaint(e);

                    this.ResumeLayout();
                }
            }
        }

        /// <summary>Overides the resize method</summary>
        /// <param name="e">Parameters for the resize event</param>
        protected override void OnResize(EventArgs e)
        {
            lock (this.controlPaintRenderLock)
            {
                lock (this.controlBufferLock)
                {
                    //Null check since resize fires before it is constructed, with the size event during parent's InitializeComponent
                    if (this.CtrlRenderTarget != null)
                    {
                        this.SuspendLayout();

                        //resize the existing control rendering target
                        this.CtrlRenderTarget.Resize(new SizeU(this.Size));

                        //I also need to resize the buffer, but can't. Instead, create a new one, then copy the existing one. Kind of lame.
                        this.ResizeBitmapRenderTarget();

                        base.OnResize(e);

                        //cause another draw
                        this.Invalidate(new Rectangle(new Point(0, 0), this.Size));

                        this.ResumeLayout();
                    }
                }
            }
        }

        /// <summary>Overridden Paint background method</summary>
        /// <param name="e">Paint event arguments</param>
        /// <remarks>
        ///     Made empty to avoid GDI and Direct2D writing to the same control; when moving the control around
        ///     or rendering at high speeds, the dreaded WinForms flicker was introduced.
        ///     The background painting can be found in the <see cref="FillBufferRenderTarget"/> method,
        ///     which fills the bitmap back buffer with the control's background color.
        /// </remarks>
        protected override void OnPaintBackground(PaintEventArgs e) {  }
        #endregion


        #region Drawing
        /// <summary>Resizes the bitmap rendering target buffer</summary>
        /// <remarks>Does not lock the GDI render target. The OnResize or other callers lock instead.</remarks>
        protected void ResizeBitmapRenderTarget()
        {
            lock (this.controlPaintRenderLock)
            {
                lock (this.controlBufferLock)
                {
                    using (BitmapRenderTarget bmpCurr = this.BmpRenderTarget)
                    {
                        BitmapRenderTarget bmpNew;

                        ResultCode result = this.CtrlRenderTarget.CreateCompatibleRenderTarget(out bmpNew);

                        this.DuplicateDoubleBufferContents(bmpNew);

                        //Property disposes and locks
                        this.BmpRenderTarget = bmpNew;
                    }
                }
            }
        }

        /// <summary>Draws a Bitmap to the render buffer</summary>
        /// <param name="bmp">Direct2D bitmap to draw to the buffer.</param>
        protected void DrawBitmapToBuffer(Direct2D.Bitmap bmp, Point2dF origin)
        {
            lock (this.controlBufferLock)
            {
                lock (this.resourceLock)
                {
                    Direct2D.SizeF bmpSize = bmp.GetSize();

                    Single width = bmpSize.Width > this.BmpRenderTarget.Size.Width ? this.BmpRenderTarget.Size.Width : bmpSize.Width;
                    Single height = bmpSize.Height > this.BmpRenderTarget.Size.Height ? this.BmpRenderTarget.Size.Height : bmpSize.Height;

                    Direct2D.RectangleF destRect = new Direct2D.RectangleF(origin.X, origin.X + width, origin.Y, origin.Y + height);
                    Direct2D.RectangleF srcRect = new Direct2D.RectangleF(0.0F, width, 0.0F, height);

                    this.BmpRenderTarget.BeginDraw();

                    this.FillBufferRenderTarget(this.BmpRenderTarget);

                    // do the actual draw
                    this.BmpRenderTarget.DrawBitmap(bmp, destRect, 1.0F, BitmapInterpolationMode.Linear, srcRect);

                    //tell Direct2D that a paint operation is ending
                    ResultCode result = this.BmpRenderTarget.EndDraw();
                }
            }
        }

        /// <summary>Draws a Bitmap to the render buffer</summary>
        /// <param name="bmp">Direct2D bitmap to draw to the buffer.</param>
        protected void DrawBitmapToBuffer(Direct2D.Bitmap bmp)
        {
            this.DrawBitmapToBuffer(bmp, new Point2dF(0.0F, 0.0F));
        }

        /// <summary>Duplicates the bitmap behind the existing rendering target, and drawing it to a new one, discarding the current and setting the new.</summary>
        /// <remarks>Does not lock any references, as the outside method locks</remarks>
        protected void DuplicateDoubleBufferContents(BitmapRenderTarget bmpNew)
        {
            Direct2D.Bitmap bmp = null;
            ResultCode result = ResultCode.Success_OK;

            if (this.HasFrameSet)
                bmp = Direct2dResourceManager.Instance.GetBitmapResource(this.currentFrameKey);
            else
                result = this.BmpRenderTarget.GetBitmap(out bmp);

            bmpNew.BeginDraw();

            this.FillBufferRenderTarget(bmpNew);

            //calculate the size to copy
            Direct2D.SizeF bmpSize = bmp.GetSize();

            Single width = bmpSize.Width > this.CtrlRenderTarget.Size.Width ? this.CtrlRenderTarget.Size.Width : bmpSize.Width;
            Single height = bmpSize.Height > this.CtrlRenderTarget.Size.Height ? this.CtrlRenderTarget.Size.Height : bmpSize.Height;

            //Determine the copy rectangle
            Direct2D.RectangleF rect = new Direct2D.RectangleF(0, width, 0, height);

            //Copy
            bmpNew.DrawBitmap(bmp, rect, 1.0F, BitmapInterpolationMode.Linear, rect);

            //conditionally disose the bitmap, don't if it is in the manager
            if (!this.HasFrameSet)
                bmp.Dispose();

            result = bmpNew.EndDraw();
        }

        /// <summary>Discards the current buffer and replaces it with a blank one.</summary>
        protected void DiscardCurrentBuffer()
        {
            lock (this.controlBufferLock)
            {
                BitmapRenderTarget bmpNew;

                // create a bitmap rendering target
                ResultCode result = this.CtrlRenderTarget.CreateCompatibleRenderTarget(out bmpNew);

                bmpNew.BeginDraw();
                this.FillBufferRenderTarget(bmpNew);
                result = bmpNew.EndDraw();

                //property locks, so no lock here
                this.BmpRenderTarget = bmpNew;  //replace the old buffer
            }
        }

        /// <summary>Fills the buffer render target with the background color</summary>
        /// <param name="renderTarget">Bitmap render target to fill</param>
        protected void FillBufferRenderTarget(BitmapRenderTarget renderTarget)
        {
            SolidColorBrush brush = null;

            ResultCode result = renderTarget.CreateSolidColorBrush(new ColorF(this.BackColor), out brush);

            renderTarget.FillRectangle(new Direct2D.RectangleF(new Rectangle(new Point(0, 0), this.Size)), brush);
            brush.Dispose();
        }
        #endregion


        #region Frame Resources
        /// <summary>Posts a Frame resource to the resource manager and returns a unique key to access it.</summary>
        /// <param name="resource">Frame to be posted.</param>
        /// <returns>A unique Int32 key</returns>
        public override Int32 AddFrameResource(Frame resource)
        {
            lock (this.resourceLock)
            {
                //create the bitmap
                BitmapProperties properties = new BitmapProperties(new PixelFormat(DXGI_ChannelFormat.FORMAT_B8G8R8A8_UNORM, AlphaMode.PreMultiplied), Direct2dResourceManager.Instance.Factory.GetDesktopDpi());
                SizeU dimensions = new SizeU(Convert.ToUInt32(resource.Pixels.Metadata.Width), Convert.ToUInt32(resource.Pixels.Metadata.Height));

                Direct2D.Bitmap bmp = null;
                ResultCode result = this.ResourceBmpRenderTarget.CreateBitmap(dimensions, properties, out bmp);

                Byte[] data = resource.Pixels.GetPixelData(ExternalPixelEnums.PixelFormat.RGBA_B8G8R8A8, ScanLineOrder.TopDown, 0, 0);
                result = bmp.CopyFromMemory(new RectangleU(dimensions), data, Convert.ToUInt32(resource.Pixels.Metadata.Width * 4));

                return Direct2dResourceManager.Instance.AddFrameResource(bmp);
            }
        }

        /// <summary>Frees a Bitmap resource in the resource manager and Disposes of it.</summary>
        /// <param name="frameKey">Direct2D Bitmap key to be Disposed.</param>
        public override void FreeFrameResource(Int32 frameKey)
        {
            lock (this.resourceLock)
            {
                if (frameKey > -1)
                    Direct2dResourceManager.Instance.FreeFrameResource(frameKey);
            }
        }
        #endregion


        #region Frame Setting
        /// <summary>Sets the frame to be rendered to the User Control</summary>
        /// <param name="key">Frame key to set as current image</param>
        public override void SetRenderFrame(Int32 key)
        {
            this.SetRenderFrame(key, 0, 0);
        }

        /// <summary>Sets the frame to be rendered to the User Control</summary>
        /// <param name="key">Frame key to set as current image</param>
        /// <param name="originX">X coordinate to start drawing from</param>
        /// <param name="originY">Y coordinate to start drawing from</param>
        public override void SetRenderFrame(Int32 key, Int64 originX, Int64 originY)
        {
            lock (this.controlBufferLock)
            {
                if (key > -1)
                    this.DrawBitmapToBuffer(Direct2dResourceManager.Instance.GetBitmapResource(key), new Point2dF(Convert.ToSingle(originX), Convert.ToSingle(originY)));
                else
                    this.DiscardCurrentBuffer();

                this.currentFrameKey = key;
            }
        }

        /// <summary>This method invokes the rendering. For use by the appliation to tell the control to change images on demand.</summary>
        public void Render()
        {
            this.Invalidate();
        }

        /// <summary>Sets the frame to be rendered to the User Control and then renders it</summary>
        /// <param name="key">Frame key to set as current image</param>
        public virtual void SetRenderFrameAndRender(Int32 key)
        {
            this.SetRenderFrameAndRender(key, false);
        }

        /// <summary>Sets the frame to be rendered to the User Control and then renders it</summary>
        /// <param name="key">Frame key to set as current image</param>
        /// <param name="freePreviousFrame">
        ///     Flag indicating whether to dispose of the previous image set
        ///     (in the case of transient images, such as composite images for a game or high-frame video playback)
        /// </param>
        public virtual void SetRenderFrameAndRender(Int32 key, Boolean freePreviousFrame)
        {
            this.SetRenderFrameAndRender(key, 0, 0, freePreviousFrame);
        }

        /// <summary>Sets the frame to be rendered to the User Control and then renders it</summary>
        /// <param name="key">Frame key to set as current image</param>
        /// <param name="originX">X coordinate to start drawing from</param>
        /// <param name="originY">Y coordinate to start drawing from</param>
        public virtual void SetRenderFrameAndRender(Int32 key, Int64 originX, Int64 originY)
        {
            this.SetRenderFrameAndRender(key, originX, originY, false);
        }

        /// <summary>Sets the frame to be rendered to the User Control and then renders it</summary>
        /// <param name="key">Frame key to set as current image</param>
        /// <param name="originX">X coordinate to start drawing from</param>
        /// <param name="originY">Y coordinate to start drawing from</param>
        /// <param name="freePreviousFrame">
        ///     Flag indicating whether to dispose of the previous image set
        /// </param>
        public virtual void SetRenderFrameAndRender(Int32 key, Int64 originX, Int64 originY, Boolean freePreviousFrame)
        {
            lock (this.controlBufferLock)
            {
                Int32 previousFrameKey = this.currentFrameKey;

                this.SetRenderFrame(key, originX, originY);
                this.Render();

                if (freePreviousFrame)
                    this.FreeFrameResource(previousFrameKey);
            }
        }
        #endregion
    }
}

Win32 Multimedia Timer Callback’s Code

Excluded for size, but here is the relevant code, linking to “winmm.dll”, EntryPoint = “timeSetEvent”

        /// <summary>Callback method for WIn32 API</summary>
        protected virtual void Win32Callback(UInt32 timerId, UInt32 message, IntPtr user, IntPtr param1, IntPtr param2)
        {
            TimeSpan raise;
            lock (this.timerLock)
            {
                //get system time for start time
                UInt32 uptime = Win32MultimediaTimeFunctions.GetEnvironmentUptime();
                Int32 upTimeSec = (Int32)(uptime / 1000);
                Int32 upTimeMilliSec = (Int32)(uptime % 1000);
                TimeSpan WinUpTime = new TimeSpan(0, 0, 0, upTimeSec, upTimeMilliSec);
                raise = WinUpTime - this.StartTime;
                //this.elapsed(raise);
                this.RaiseTimer(raise);
            }

            //Note: outside the lock, this.elapse(raise) kills the display driver
            //inside, without threading, it is fine.
            //inside, with threading, the display driver will crash after a bit of playback
        }

        protected void RaiseTimer(TimeSpan elapsedTime)
        {
            Thread timerEvent = new Thread(() => { this.RunThread(elapsedTime); });
            timerEvent.IsBackground = true;
            timerEvent.Name = "Timer callback";
            timerEvent.Start();
        }

        /// <summary>Raises the timer on a separate thread</summary>
        protected void RunThread(TimeSpan elapsedTime)
        {
            if (this.threadLock.WaitOne(0))
            {
                this.elapsed(elapsedTime);
                this.threadLock.ReleaseMutex();
            }
        }

Conclusion

After 3 weeks, I’m not ashamed to say I’m baffled by this behavior, and looking for any sort of input for identifying a race condition, something that I might be missing, architecturally speaking, about Direc2D or where I’m just showing my ignorance.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-03T05:51:39+00:00Added an answer on June 3, 2026 at 5:51 am

    All locks statements in the code seems to be an over complicated solution. Also creating COM objects (like Direct2D1) from constructors and using them from thread UI methods is usually not a good practice.

    I would simplify your application by performing all device/objects creation and rendering on the same thread, also by keeping your rendering code outside the form. Ideally, this should be totally independent, as you could render to any kind of windows/controls via the HWND or to a DXGI surface, or to a Windows 8 Metro surface.

    Also, as Aren suggest, instead of using your own Direct2D1 wrapper, you should rely on an existing robust wrapper like SharpDX. It will save you to maintain a costly layer and help you to focus on your specific application.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

To have a general-purpose documentation system that can extract inline documentation of multiple languages,
I'm currently writing some general purpose .net libraries that contain usual helper classes. For
So I have this general purpose HashTable class I'm developing, and I want to
I'd like one general purpose function that could be used with any Flags style
It seems like a general purpose need on the web that a page can
Can I load a floating point from a general purpose register like this: lwc1
Is there a general purpose function in Objective-C that I can plug into my
I'm looking for a general purpose API/web service/tool/etc... that allows convert a given HTML
I'm developing a general purpose library which uses Win32's HeapAlloc MSDN doesn't mention alignment
General-purpose computing on graphics processing units ( GPGPU ) is a very attractive concept

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.