Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用一个线程来更新c中Windows窗体中的面板#_C#_Multithreading_Winforms_Clock - Fatal编程技术网

C# 如何使用一个线程来更新c中Windows窗体中的面板#

C# 如何使用一个线程来更新c中Windows窗体中的面板#,c#,multithreading,winforms,clock,C#,Multithreading,Winforms,Clock,我有一个StillClock类,它是一个面板,实现如下: public class StillClock: Panel { private int hour; private int minute; private int second; /** Construct a default clock with the current time*/ public StillClock() { this.Size= new Size(200,200);

我有一个StillClock类,它是一个面板,实现如下:

public class StillClock:  Panel {
  private int hour;
  private int minute;
  private int second;

  /** Construct a default clock with the current time*/
  public StillClock() {
      this.Size= new Size(200,200);
      this.Paint += OnPaint;
      setCurrentTime();
  }

  /** Construct a clock with specified hour, minute, and second */
  public StillClock(int hour, int minute, int second) {
    this.hour = hour;
    this.minute = minute;
    this.second = second;
  }

  /** Return hour */
  public int getHour() {
    return hour;
  }

  /** Set a new hour */
  public void setHour(int hour) {
    this.hour = hour;
    this.Refresh();
  }

  /** Return minute */
  public int getMinute() {
    return minute;
  }

  /** Set a new minute */
  public void setMinute(int minute) {
    this.minute = minute;
    this.Refresh();
  }

  /** Return second */
  public int getSecond() {
    return second;
  }

  /** Set a new second */
  public void setSecond(int second) {
    this.second = second;
    this.Refresh();
  }

  /** Draw the clock */
  private  void OnPaint(object sender, PaintEventArgs e) {

      Graphics g = e.Graphics;
    // Initialize clock parameters
    int clockRadius =
      (int)(Math.Min(this.Size.Width , this.Size.Height ) * 0.8 * 0.5);
    float xCenter = Size.Width / 2.0f;
    float yCenter = Size.Height / 2.0f;

    // Draw circle
    Pen pen = new Pen(Color.Black);
    g.DrawEllipse(pen,xCenter - clockRadius, yCenter - clockRadius,
      2 * clockRadius, 2 * clockRadius );

    g.DrawString( "12", new Font("System", 8), new SolidBrush(Color.Black),  xCenter - 5f,   yCenter - clockRadius + 12f -10);
    g.DrawString("9", new Font("System", 8), new SolidBrush(Color.Black), xCenter - clockRadius + 3f, yCenter + 5f - 10);
    g.DrawString("3", new Font("System", 8), new SolidBrush(Color.Black), xCenter + clockRadius - 10f, yCenter + 3f - 10);
    g.DrawString("6", new Font("System", 8), new SolidBrush(Color.Black), xCenter - 3f, yCenter + clockRadius - 3f - 10);

    // Draw second hand
    int sLength = (int)(clockRadius * 0.8);
    int xSecond = (int)(xCenter + sLength *
      Math.Sin(second * (2 * Math.PI / 60)));
    int ySecond = (int)(yCenter - sLength *
      Math.Cos(second * (2 * Math.PI / 60)));

    g.DrawLine(new Pen(Color.Red), xCenter, yCenter, xSecond, ySecond);

    // Draw minute hand
    int mLength = (int)(clockRadius * 0.65);
    int xMinute = (int)(xCenter + mLength *
      Math.Sin(minute * (2 * Math.PI / 60)));
    int yMinute = (int)(yCenter - mLength *
      Math.Cos(minute * (2 * Math.PI / 60)));

    g.DrawLine(new Pen(Color.Blue), xCenter, yCenter, xMinute, yMinute);

    // Draw hour hand
    int hLength = (int)(clockRadius * 0.5);
    int xHour = (int)(xCenter + hLength *
      Math.Sin((hour % 12 + minute / 60.0) * (2 * Math.PI / 12)));
    int yHour = (int)(yCenter - hLength *
      Math.Cos((hour % 12 + minute / 60.0) * (2 * Math.PI / 12)));

    g.DrawLine(new Pen(Color.Black), (float)xCenter, (float)yCenter, (float)xHour, (float)yHour);
  }

  public void setCurrentTime() {
    // Construct a calendar for the current date and time
    Thread.sleep(1000);
    // Set current hour, minute and second
    this.hour = DateTime.Now.Hour;
    this.minute = DateTime.Now.Minute;
    this.second = DateTime.Now.Second;
  }
 }
我必须继承类ClockAnimationUsingThread from类StillClock来开发一个动画时钟,使用Thread对象每1000毫秒设置一次StillClock的时间

我试着这样做:

public class ClockAnimationUsingThread : StillClock
    {
        public ClockAnimationUsingThread()
        {
            Thread thread1 = new Thread(new ThreadStart(this.setCurrentTime));
            thread1.Start();
        }
    }
然后:

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            var panel = new ThreadedClock_ClassLibrary.ClockAnimationUsingThread();
            this.Controls.Add(panel);
        }
    }

在Form1类中,但启动后,它只生成静态时钟,根本不更新它。

为了纠正此问题并显示线程如何工作,请执行以下操作:

这样做:

public class ClockAnimationUsingThread : StillClock
{
    public ClockAnimationUsingThread()
    {
    }

    public void Start()
    {
        Thread thread1 = new Thread(new ThreadStart(this.setCurrentTime));
        thread1.Start();
    }

}
那么这个,

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        var panel = new ThreadedClock_ClassLibrary.ClockAnimationUsingThread();
        this.Controls.Add(panel);
        panel.Start();
    }
}
我把它放在一个循环中,这样线程将每1000毫秒持续更新一次,如果你将线程设置为后台线程,那么当应用程序关闭时,它将中止。如果不想让它等待,那么需要在while循环中放入一些布尔属性,然后在关闭表单时将其设置为false

public void setCurrentTime() {
// Construct a calendar for the current date and time
while(true){
// Set current hour, minute and second
   this.Invoke((MethodInvoker) delegate {
   this.hour = DateTime.Now.Hour;
   this.minute = DateTime.Now.Minute;
   this.second = DateTime.Now.Second;
   });

   Thread.sleep(1000);
 }


}

您必须让UI线程知道它需要重新绘制时钟。只需添加:

  this.Invalidate();

这是线程安全的,不需要调用UI线程。请注意,每秒只运行一次微秒级的代码就消耗掉整个线程是非常浪费的。一个简单的计时器也可以完成这项工作,而且要便宜得多。当然,当窗口关闭时,您不应该让线程继续运行,这也解决了您的关机问题。

您是否尝试过在面板上调用
Refresh()
Redraw()
?除非您使用的是Invokes,否则我认为控件不会自动更新(甚至可能不会)。注意您是如何在小时设置程序中调用
this.Refresh()
,而不是其他程序的?您不应该尝试从不“拥有”该UI的后台线程更新WinForms UI。改为调用.BeginInvoke。您需要显示您的方法“setCurrentTime”@RobertHarvey,您的确切意思是将.Refresh()或.Redraw()放在哪里?请查看您的
setHour()
方法。请参见此处的
this.Refresh()
?但是,请注意其他人的警告,您可能需要调用这些操作。在创建窗口句柄之前,不能对控件调用Invoke或BeginInvoke。要将代码移出构造函数,请创建一个名为Start()的新方法。将线程创建代码放在那里,在添加面板等后调用Start()。我同意你的答案。。。我应该这么说!我的回答是正确的,我被卷入了试图修正他的密码中。这个密码只是为了练习。这不是生产或任何东西。我只是想知道如何通过一个线程对象来实现这一点,它必须搞乱GUI。好吧,指出你在练习时做了一些非常错误的事情应该是相关的。可能会变成坏习惯。请结束你的问题。