调用:我如何从后台工作分配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个小时没有成功,而且我几乎从来没有找不到工作代码示例,即使我不得不费力地浏览几十个劣质答案。对于这个问题有大量相互矛盾的答案,这取决于文章的发布日期和所建议的方法。
如果我立即Thread.Sleep() 200ms, Invoke方法确实有效。还没有测试过下限,但它在不同的机器上不会一致,所以报告它不会提供信息。
更新此代码
...
m_fp.Unlock();
var capturedBitmap = m_fp.Bitmap.Clone();
Invoke((MethodInvoker)delegate { pictureBox1.Image = capturedBitmap; });
...
你可能会得到红色的x,因为你正在修改位图,因为你把它分配给图片框。复制位图,这样你就不会在你的图片框里玩了。