Jump to content

WorkerThreadExeption: Object is currently in use elsewhere


midora
 Share

Recommended Posts

I'm fighting with this issue, maybe someone can provide a hint.

 

In an effect plugin I created a class and four instances of the class.

The class contains as a member an array of matrices.

 

OnSetRenderInfo() calls a member function of the instances to setup these arrays of matrices.

OnRender() uses the instances and the matrices to transform points.

 

Now quite often I'm getting the above exception. OnRender() does not modify the matrices. They are just used to do the transformation job. So I would say the matrices are used read only. But for sure it may happen that two WorkerThreads are accessing the same matrix at the same time.

 

It just happens with the matrix member not with other member variables of the instances.

 

 

midoras signature.gif

Link to comment
Share on other sites

BTW: I'm using the following code snippet to avoid the exeption. But for sure it slows down the rendering.

So I'm still looking for a better solution.

 

Matrix m;
lock (model.matrices[iFace])
{
    m = model.matrices[iFace].Clone();
}

midoras signature.gif

Link to comment
Share on other sites

If you're using GDI+ classes like Matrix, you can't use them on multiple threads at the same time. Locking or cloning are the two solutions. Or, don't use GDI+.

 

There are some better ways to do what you need, but the ones I'm thinking of all requires .NET 4.0. Since Paint.NET v3.5.10 operates on .NET 3.5 SP1, you'd have to hand-roll an object pool instead of using System.Collections.Concurrent.ConcurrentBag. It wouldn't be too hard though ... a Dictionary<TKey, Stack<TValue>> with locking around all accesses to it would probably work.

 

(GDI+ == System.Drawing)

The Paint.NET Blog: https://blog.getpaint.net/

Donations are always appreciated! https://www.getpaint.net/donate.html

forumSig_bmwE60.jpg

Link to comment
Share on other sites

Even cloning failed in OnRender() and this should be a readonly action. And it is not possible to clone in SetRenderInfo because the number of WorkerThreads is unknown ;-)

 

In the meantime I started to replace the Matrix class with my own one. Not because of this issue but Matrix.TransformPoints is really slow. Just replacing this function call improved the rendering speed of the animation in kaleidocycles from 10s to 1.1s...

 

I'm still dreaming that 4.0 would provide a warping methode for polygons on source and dest surface so that I can get rid of this:

 

 

        /*---------------------------------------------------------------------------*\
        Function    GetBilinearPolygonSamples
        Purpose     Copies an polygonal area from <src> to <dst> respecting a matrix
                    transformation and a clipping rectangle.
        Remarks     The final method of src should not use g and src as parameters.
        \*---------------------------------------------------------------------------*/

        private void GetBilinearPolygonSamples(Graphics g, Surface src, Surface dst, PointF[] polygonDst, Rectangle clipRectDst, Matrix mDstToSrc)
        {
            GraphicsPath gpDst = new GraphicsPath();
            gpDst.AddPolygon(polygonDst);

            // Now get for all points in the dst triangle the bilinear samples of src
            Region region = new Region(gpDst);
            region.Intersect(clipRectDst);
            if (region.IsEmpty(g)) return;

            float[] m = mDstToSrc.Elements;
                //! mDstToSrc.TransformPoints(point) is more than 10 times slower than to get the elements and do the multiplication yourself

            RectangleF[] rects = region.GetRegionScans(new Matrix());
            for (int ri = 0; ri < rects.Length; ri++)
            {
                RectangleF rect = rects[ri];
                for (int y = (int)rect.Top; y < rect.Bottom; y++)
                {
                    for (int x = (int)rect.Left; x < rect.Right; x++)
                    {
                        float pointX = x * m[0] + y * m[2] + m[4];
                        float pointY = x * m[1] + y * m[3] + m[5];

                        dst[(int)x, (int)y] = src.GetBilinearSample(pointX, pointY);
                    }
                }
            }
        } /* GetBilinearPolygonSamples */

 

Any idea for an improvement in the moment?

midoras signature.gif

Link to comment
Share on other sites

What? Paint.NET 4.0 won't be providing anything of the sort ... I have no idea where you got that idea from.

 

If you want speed, don't use the GDI+ classes. Whether that's Matrix, Region, GraphicsPath, etc. Don't use them. They're slow.

The Paint.NET Blog: https://blog.getpaint.net/

Donations are always appreciated! https://www.getpaint.net/donate.html

forumSig_bmwE60.jpg

Link to comment
Share on other sites

  • 2 weeks later...

I'm not talking about any gdi extension. I'm just using GDI in the moment to get the region scans.

 

I'm looking for a transformation function from a source to a destination surface which works on a polygon (or maybe just a triangle). You are providing GetBilinearPixel() already to make it easier for a plugin to get an interpolated pixel. A simular funtion for an area would allow plugins to profit from any speed enhancement in Paint.NET. I would expect that there is already such a funtion used in the layer rotate/zoom function.

midoras signature.gif

Link to comment
Share on other sites

GetBilinearPixel() is there because it's used by built-in effects and of obvious utility to many plugins.

 

Rotate/Zoom doesn't work the way you are thinking it does.

 

Like I said, I'm not going to be implementing a bitmap perspective/polygon transformation gizmo for you. That's your job! I don't know why you'd expect it to already be provided for you.

The Paint.NET Blog: https://blog.getpaint.net/

Donations are always appreciated! https://www.getpaint.net/donate.html

forumSig_bmwE60.jpg

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...