跨线程控制
我目前正在尝试创建一个计时器,每隔几毫秒运行一段代码。问题是我希望能够修改与计时器在同一线程上创建的图片框的位置,即使它不是在原始线程上创建的,我最终也会收到调用对象错误?
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;
}
}
希望我不必调用我在此线程上声明的每个控件,因为计划是制作图片框列表,以便用户可以根据需要添加图片框。
感谢您的帮助。
I'm currently trying to create a timer that will run a chunk of code every few milliseconds. the problem is i want to be able to Modify the position of a picture box that is created on the same thread as the timer, I end up getting the Invoke object error even though its not created on the original thread ?
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;
}
}
hoping i don't have to invoke every control i declare on this thread as the plan was to make a picture box list, so the user could add picture boxes as needed.
Thanks For the help.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您应该使用 System.Windows.Forms.Timer 而不是创建自己的线程。
这样,一切都将已经在 UI 线程上。
You should use a System.Windows.Forms.Timer instead of creating your own thread.
This way, everthying will already be on the UI thread.
应使用相同的
InvokeRequired
和Invoke
(或BeginInvoke
)来设置PictureBox.Location
。控件属性必须在创建控件句柄的线程上设置,这是由 WinForms 决定的,而不是在创建控件本身的位置。Control.InvokeRequired。
以下是有关Windows 窗体控件中的多线程的详细信息,其中包括以下示例使用后台线程。
The same
InvokeRequired
andInvoke
(orBeginInvoke
) should be used to setPictureBox.Location
. Control properties must be set on the thread where the control handle was created, that is decided by WinForms, not where the control itself was created.The reasons are explained in Control.InvokeRequired.
Here is more information on multithreading in Windows Forms Controls that includes an example of using a background thread.