我在後臺線程中執行所有昂貴的計算,並且需要在每個計算週期後分配pictureBox1.Image。我用代表來做這件事,但它已經很長時間了,事情似乎不再那樣了。如何從BackgroundThread更新PictureBox?
我試圖把在WorkerCompleted事件處理程序的任務,但我無法弄清楚如何重新啓動backgroundWorker1。我一整天都在這裏,感到非常沮喪,這種用法很容易做到。
這是代碼的最相關的部分:
using System;
using System.Globalization;
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;
double[,][] distances = new double[3000, 3000][];
FastPixel m_fp;
public Form1()
{
InitializeComponent();
WindowState = FormWindowState.Maximized;
this.pictureBox1.LoadCompleted += new System.ComponentModel.AsyncCompletedEventHandler(PictureBox1_LoadCompleted);
CoordinateSystem.AssignMe(this);
}
private void Form1_Load(object sender, EventArgs e)
{
ReadColors(); // Reads text file alternating name and RGB hex of
// Wikipedia's 1200+ named colors.
Point3D p = new Point3D(127.5, 127.5, 127.5);
foreach (FoundColors fc in m_lColors.Values)
fc.pt = fc.color - p;
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();
private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
double fAngle, fRadius, d;
Point3D vU, vV;
Point pLocation = new Point();
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();
}
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 backgroundWorker1_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
{
pictureBox1.Image = m_fp.Bitmap;
}
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));
}
}
}
而且這是我支持的代碼部分:
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; }
}
}
}
多的支持代碼:
[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() { }
}
發佈您試圖做的事情。 –
數據綁定呢?使用本地設置並將圖片框綁定到它,然後使用INotifyPropertyChanged界面 –
您知道無法從後臺線程更新UI嗎?你需要獲得UI線程來更新UI的東西 - SO包含Q/A如何做到這一點。然後關於如何讓背景重新開始,一種方法可能是有一個計時器並提供背景函數作爲回調;計時器開始啓動回撥;回調會停止定時器,它會阻止,調用UI線程的調度器來更新UI,然後再次啓動定時器,從而再次啓動整個過程。 – eurotrash