调用:我如何从后台工作分配UI对象?c#

本文关键字:UI 分配 对象 工作 后台 调用 | 更新日期: 2023-09-27 18:15:05

这是我的代码的核心。我试过调用每一种方式到中国,但我总是得到相同的大红色X和一个objectdispose异常在Form1。(为了简洁,删去了不相关的代码)

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;
            }
        }
    }
}

最后是一些支持代码,coordinatessystem .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事件(当然是在Properties中启用它之后)和各种形式的委托。对于老的代表来说,这是一件相当简单的事情,但我今天花了10个小时没有成功,而且我几乎从来没有找不到工作代码示例,即使我不得不费力地浏览几十个劣质答案。对于这个问题有大量相互矛盾的答案,这取决于文章的发布日期和所建议的方法。

调用:我如何从后台工作分配UI对象?c#

如果我立即Thread.Sleep() 200ms, Invoke方法确实有效。还没有测试过下限,但它在不同的机器上不会一致,所以报告它不会提供信息。

更新此代码

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

你可能会得到红色的x,因为你正在修改位图,因为你把它分配给图片框。复制位图,这样你就不会在你的图片框里玩了。