2012-02-05 29 views
3

我目前正在尝试创建一个计时器,每隔几毫秒就会运行一段代码。问题是我希望能够修改与定时器在同一个线程上创建的图片框的位置,我最终得到了Invoke对象错误,即使它没有在原始线程上创建?跨线程控件

private void frmMain_Load(object sender, EventArgs e) 
{ 
    //Update Timer Thread 
    UpdateThread = new Thread(new ThreadStart(UpdateWindow)); 
    SleepTime = (int)1000/MaxFps; 
    UpdateThread.Start();   
    //..... 
} 

delegate void SetTextCB(string text); 
delegate void SetControl(Control cntrl); 

public void TimerThread() 
{ 
    //Controls 
    PictureBox TestPicBox; 

    //Test TestPicBox 
    TestPicBox = new PictureBox(); 
    TestPicBox.Image = Image.FromFile(TestImage.bmp"); 
    TestPicBox.Top = 20; 
    TestPicBox.Left = 20; 
    TestPicBox.Width = 64; 
    TestPicBox.Height = 64; 
    FilePanelControl(TestPicBox); 

    while (true) 
    { 
     //--Sleep 
     Thread.Sleep(SleepTime); 
     //--FPS 
     if (DateTime.Now.ToString("HH:mm:ss") != SystemTime) 
     { 
      if (blnShowFps) { lblFpsTextsSet(UpdateFps.ToString() + "-FPS"); } 
      else { lblFpsTextsSet(""); } 
      SystemTime = DateTime.Now.ToString("HH:mm:ss"); 
      UpdateFps = 0; 
     } 
     UpdateFps++; 
     //Sleep Time 
     SleepTime = (int)1000/MaxFps; 

     //Do UpDate Logic 
     TestPicBox.location = new point(10,10); 
    } 
} 

//--Add Control 
private void FilePanelControl(Control added) 
{ 
    if (this.FilePanel.InvokeRequired) 
    { 
     SetControl d = new SetControl(FilePanelControl); 
     this.Invoke(d, new object[] { added }); 
    } 
    else 
    { 
     this.FilePanel.Controls.Add(added); 
    } 
} 

//--lblFps.text 
private void lblFpsTextsSet(string text) 
{ 
    if (this.lblFPS.InvokeRequired) 
    { 
     SetTextCB d = new SetTextCB(lblFpsTextsSet); 
     this.Invoke(d, new object[] { text }); 
    } 
    else 
    { 
     this.lblFPS.Text = text; 
    } 
} 

希望我不必调用每个控件我在此线程声明为我们的计划是做一个图片框列表,以便在需要的用户可以添加图片框。

感谢您的帮助。

回答

1

应该使用相同的InvokeRequiredInvoke(或BeginInvoke)来设置PictureBox.Location。控件属性必须在创建控件句柄的线程上设置,这由WinForms决定,而不是控件本身的创建位置。

的原因在Control.InvokeRequired解释。

这里是multithreading in Windows Forms Controls,其包括使用后台线程的一个例子的更多信息。

+0

不完全是我想要的,但谢谢 – Dusty 2012-02-07 01:34:03

3

您应该使用System.Windows.Forms.Timer代替创建自己的线程。

这样,everthying将已经在UI线程上。

+0

窗户计时器是不准确的,缓慢的,如果其设置为1毫秒运行我只得到64fps虽然它应该在1000上运行或接近它 – Dusty 2012-02-05 23:03:25

+0

不要运行每毫秒;毫无意义。你应该瞄准大约30 FPS。事实上,我会建议每100ms运行一次。 – SLaks 2012-02-05 23:06:49

+0

我不打算快速运行它,但我希望能够以60-100fps精确运行它 – Dusty 2012-02-05 23:09:26