2015-09-29 73 views
-2

我在後臺線程中執行所有昂貴的計算,並且需要在每個計算週期後分配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() { } 
    } 
+2

發佈您試圖做的事情。 –

+0

數據綁定呢?使用本地設置並將圖片框綁定到它,然後使用INotifyPropertyChanged界面 –

+0

您知道無法從後臺線程更新UI嗎?你需要獲得UI線程來更新UI的東西 - SO包含Q/A如何做到這一點。然後關於如何讓背景重新開始,一種方法可能是有一個計時器並提供背景函數作爲回調;計時器開始啓動回撥;回調會停止定時器,它會阻止,調用UI線程的調度器來更新UI,然後再次啓動定時器,從而再次啓動整個過程。 – eurotrash

回答

-1

開放一個新的線程,並創建一個功能

Worker workerObject = new Worker(); 
Thread workerThread = new Thread(workerObject.DoWork); 

workerThread.Start(); 

public void DoWork() 
{ 
    while (!_shouldStop) 
    { 
     //REFRESH YOUR IMAGE 
    } 
} 
+2

這是可怕的建議,它不會工作! –

+1

發佈你的代碼@MikeDinescu – blackghost

+0

普通的孩子把你的代碼 – blackghost

0

如果我馬上使用Thread.Sleep()200毫秒,Invoke方法就可以工作。

  m_fp.Unlock(); 
      this.Invoke((MethodInvoker)delegate() { pictureBox1.Image = m_fp.Bitmap; }); 
      Thread.Sleep(200); 
     } while (true); 

未測試下限,但它不會在機器間保持一致,因此報告不會提供信息。