簡體   English   中英

調用:如何從BackgroundWorker分配UI obj? C#

[英]Invoke: how can I assign UI obj from BackgroundWorker? C#

這是我代碼的核心。 我曾經嘗試過Invoke到中國的所有方式,但是在Form1上我總是得到相同的大紅色X和ObjectDisposed異常。 (為簡潔起見,編輯了不相關的代碼。)

using System;
using System.Globalization;
using System.ComponentModel;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using KnownColorsPalette;

namespace Color_Visualizer
{
    public partial class Form1 : Form
    {
        static CultureInfo m_culture = CultureInfo.CurrentCulture;
        FastPixel m_fp; // FastPixel encapsulates 
                        // Bitmap.LockBits() funcs & data

        private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
            double fAngle, fRadius, d;
            Point3D vU, vV;
            Point pLocation = new Point();

            do
            {
                m_pNormal = Coord.Plane.Normal;

                fAngle = Math.Atan2(m_pNormal.y, m_pNormal.x);
                fRadius = Math.Sqrt(m_pNormal.x * m_pNormal.x + m_pNormal.y * m_pNormal.y);
                fAngle += fSpeed * 180 / Math.PI;
                m_pNormal.x = Math.Cos(fAngle) * fRadius;
                m_pNormal.y = Math.Sin(fAngle) * fRadius;

                m_fp.Lock();
                m_fp.Clear(Color.Black);
                foreach (FoundColors fc in m_lColors.Values)
                {
                    vU = new Point3D(Coord.U);
                    d = dist(fc.pt, ref vU);
                    vV = Coord.V;
                    vV.mult(d);

                    pLocation.X = (int)(m_midHoriz + vU.norm());
                    pLocation.Y = (int)(m_midVert + vV.norm());
                    m_fp.SetPixel(pLocation, fc.color);
                }
                m_fp.Unlock();
                Invoke((MethodInvoker)delegate { pictureBox1.Image = m_fp.Bitmap; });
            } while (true);
        }


        public Form1()
        {
            InitializeComponent();
            WindowState = FormWindowState.Maximized;
            CoordinateSystem.AssignMe(this);
        }

        void ReadColors() // I saved all of Wikipedia's 1200+ named colors
        {                 // as a text file.
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            ReadColors();

            Point3D p = new Point3D(127.5, 127.5, 127.5);
            foreach (FoundColors fc in m_lColors.Values)
                fc.pt = fc.color - p; // My Point3D class has 
                           // implicit operator casts to and
                           // from Color.

            Coord = new CoordinateSystem(new Plane(new Point3D(-127.5, -127.5, -127.5), new Point3D(-1, 0, 0)));
            backgroundWorker1.RunWorkerAsync();
        }


        double fSpeed = 5;
        Point3D m_pNormal = new Point3D();

        double m_fDist, m_fDot;
        public double dist(Point3D pt, ref Point3D vU)
        {
            double c1 = pt.dot(vU);
            double c2 = vU.dot(vU);
            double b = c1 / c2;
            vU.mult(b);
            //m_fDot = pt.dot(Coord.Normal);
            m_fDist = pt.norm(pt - vU);
            return m_fDist;
        }

        double m_midHoriz, m_midVert;
        private void Form1_Resize(object sender, EventArgs e)
        {
            m_midHoriz = pictureBox1.Width / 2;
            m_midVert = pictureBox1.Height / 2;
            m_fp = new FastPixel(new Bitmap(pictureBox1.Width, pictureBox1.Height));
        }
    }
}

這只是支持代碼,並不是我的問題的核心:Sorting.cs

using System.Collections.Generic;
using System.Drawing;
using System.Diagnostics;
using System.Windows.Forms;
using KnownColorsPalette;

namespace Color_Visualizer
{
    public partial class Form1 : Form
    {
        public static ColorComp m_compClr = new ColorComp();
        public static NameComp m_compName = new NameComp();
        SortedList<Color, FoundColors> m_lColors = new SortedList<Color, FoundColors>(m_compClr);
        SortedList<string, FoundColors> m_lColorByName = new SortedList<string, FoundColors>(m_compName);

        [DebuggerDisplayAttribute("{name}, R={color.R}, G={color.G}, B={color.B}")]
        class FoundColors
        {
            public Color color = Color.Empty;
            public string name = "";
            public CIELab_Color cLab;
            public Point3D pt;
            public List<int> lClosest = new List<int>();
            public int nFarthest;
            public FoundColors(FoundColors fc)
            {
                color = fc.color;
                name = fc.name;
                cLab = new CIELab_Color(fc.cLab.CIE_L, fc.cLab.CIE_a, fc.cLab.CIE_b);
                lClosest.AddRange(fc.lClosest);
                nFarthest = fc.nFarthest;
            }
            public FoundColors() { }
        }


        struct sort
        {
            public double dist;
            public int index;
            public sort(double _d, int _i) { dist = _d; index = _i; }
        }

        class DistComp : IComparer<sort>
        {
            int IComparer<sort>.Compare(sort x, sort y)
            {
                if ((object)x == null)
                    if ((object)y == null)
                        return 0;
                    else
                        return -1;

                if ((object)y == null) return 1;

                if (x.dist > y.dist) return -1;

                return 1;
            }
        }


        public class NameComp : IComparer<string>
        {
            int IComparer<string>.Compare(string x, string y)
            {
                if ((object)x == null)
                    if ((object)y == null)
                        return 0;
                    else
                        return -1;

                if ((object)y == null) return 1;

                return x.CompareTo(y);
            }
        }

        public class ColorComp : IComparer<Color>
        {
            int IComparer<Color>.Compare(Color x, Color y)
            {
                if ((object)x == null)
                    if ((object)y == null)
                        return 0;
                    else
                        return -1;

                if ((object)y == null) return 1;

                if (x.R > y.R)
                    return -1;
                else if (x.R < y.R)
                    return 1;
                else if (x.G > y.G)
                    return -1;
                else if (x.G < y.G)
                    return 1;
                else if (x.B > y.B)
                    return -1;
                else if (x.B < y.B)
                    return 1;

                return 0;
            }
        }
    }
}

最后,還有更多支持代碼CoordinateSystem.cs:

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

namespace Color_Visualizer
{

    public partial class Form1 : Form
    {
        class CoordinateSystem
        {
            const int MAX = 256;
            const double PlaneWidth = 600;

            static Form1 Me;
            static Point3D axisZ = new Point3D(0, 0, 1);
            static Point3D axisY = new Point3D(0, 1, 0);
            private Plane m_plane = new Plane(new Point3D(128, 128, 128), new Point3D(-128, 0, 0));
            private Point3D m_pV = new Point3D(0, 0, 0);
            private Point3D m_pU = new Point3D(0, 0, 0);
            private double m_fInc;

            public CoordinateSystem(Plane axAxis)
            {
                m_fInc = PlaneWidth / Me.ClientSize.Height;
                Plane = axAxis;
            }
            public static void AssignMe(Form1 form) { Me = form; }
            public Point3D U { get { return m_pU; } protected set { m_pU = value; } }
            public Point3D V { get { return m_pV; } protected set { m_pV = value; } }
            public Point3D Normal { get { return m_plane.Normal; } set { m_plane.Normal = value; } }
            static double COSerror = 0.99619469809174553229501040247389;

            public Plane Plane
            { 
                get { return m_plane; }
                set {
                    m_plane = value;
                    if (m_plane.dot(axisZ) > COSerror)
                        U = U.cross(m_plane, axisY);
                    else
                        U = U.cross(m_plane, axisZ);
                    U.div(U.norm());
                    V = U.cross(U, m_plane);
                    V.div(V.norm());
                }
            }
        }

        [DebuggerDisplayAttribute("x = {x}, y = {y}, z = {z}")]
        public class Point3D
        {
            public double x, y, z;

            public Point3D(double _x, double _y, double _z) { x = _x; y = _y; z = _z; }
            public Point3D(Point3D p) { x = p.x; y = p.y; z = p.z; }
            public Point3D() { x = 0; y = 0; z = 0; }
            public bool Equals(Point3D p) { return x == p.x & y == p.y & z == p.z; }
            public override bool Equals(object obj) { return Equals((Point3D)obj); }
            public static bool operator ==(Point3D p1, Point3D p2) { return p1.Equals(p2); }
            public static bool operator !=(Point3D p1, Point3D p2) { return !p1.Equals(p2); }
            public static Point3D operator -(Point3D e, Point3D s) { return new Point3D(e.x - s.x, e.y - s.y, e.z - s.z); }
            public static Point3D operator +(Point3D e, Point3D s) { return new Point3D(e.x + s.x, e.y + s.y, e.z + s.z); }
            public static Point3D operator *(double m, Point3D v) { return new Point3D(m * v.x, m * v.y, m * v.z); }
            public static Point3D operator *(Point3D v, double m) { return new Point3D(v.x / m, v.y / m, v.z / m); }
            public static Point3D operator /(double m, Point3D v) { return new Point3D(m * v.x, m * v.y, m * v.z); }
            public static Point3D operator /(Point3D v, double m) { return new Point3D(v.x / m, v.y / m, v.z / m); }
            public static implicit operator Color(Point3D p) { return Color.FromArgb((int)p.x, (int)p.y, (int)p.z); }
            public static implicit operator Point3D(Color c) { return new Point3D(c.R, c.G, c.B); }
            //public override int GetHashCode()
            //{
            //    unchecked
            //    {
            //        var hash = new SpookyHash();
            //        hash.Update(x);
            //        hash.Update(y);
            //        hash.Update(z);
            //        return hash.Final().GetHashCode();
            //    }
            //}

            // dot product (3D) which allows vector operations in arguments
            public double dot(Point3D u, Point3D v) { return u.x * v.x + u.y * v.y + u.z * v.z; }
            public double dot(Point3D u) { return u.x * x + u.y * y + u.z * z; }
            public double norm(Point3D v) { return Math.Sqrt(dot(v, v)); }     // norm = length of  vector
            public double norm() { return Math.Sqrt(dot(this, this)); }     // norm = length of  vector
            public double dist(Point3D u, Point3D v) { return norm(u - v); }         // distance = norm of difference
            public double dist(Point3D u) { return norm(this - u); }
            public Point3D cross(Point3D u, Point3D v) { return new Point3D(u.y * v.z - u.z * v.y, u.z * v.x - u.x * v.z, u.x * v.y - u.y * v.x); }
            public Point3D cross(Point3D u) { return new Point3D(u.y * z - u.z * y, u.z * x - u.x * z, u.x * y - u.y * x); }
            public void add(Point3D p) { x += p.x; y += p.y; z += p.z; }
            public void mult(double m) { x *= m; y *= m; z *= m; }
            public void div(double m) { x /= m; y /= m; z /= m; }
        }


        class Plane : Point3D
        {
            Point3D m_pNormal;

            public Plane(Point3D pOrigin, Point3D pNormal) : base(pOrigin) { m_pNormal = pNormal; }
            public Plane(Point3D p) : base(p) { }
            public Plane(double x, double y, double z) : base(x, y, z) { }
            public Point3D Normal { get { return m_pNormal; } set { m_pNormal = value; } }
            public double PointToPlane(Point3D p) { return p.dot(Normal); }
        }


        private CoordinateSystem m_coordSys;
        private CoordinateSystem Coord
        {
            get { return m_coordSys; }
            set { m_coordSys = value; }
    }
}

只有第一個代碼段與該問題確實相關,但是我知道有人會問這個問題,因此我提供了很多支持代碼。

請注意,我還嘗試了諸如ProgressChanged事件(當然,在“屬性”中啟用它)和各種形式的委托這樣的事情。 對於以前的代表來說,這過去是一件相當簡單的事情,但是我今天花了10個小時沒有成功,即使我不得不經過許多次等的回答,我幾乎也不會找到有效的代碼示例。 根據帖子的日期和建議的處理方式,對這個問題有很多矛盾的答案。

如果我立即Thread.Sleep()持續200ms,則Invoke方法確實起作用。 還沒有測試下限,但是在機器之間它並不一致,因此報告它不會提供更多信息。

更新此代碼

...
m_fp.Unlock();
var capturedBitmap = m_fp.Bitmap.Clone();
Invoke((MethodInvoker)delegate { pictureBox1.Image = capturedBitmap; });
...

您可能會得到紅色x,因為在將位圖分配給圖片框時正在對其進行修改。 克隆位圖,這樣就不會在圖片框中玩位圖了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM