跨线程控制

发布于 2025-01-03 11:57:47 字数 1919 浏览 5 评论 0原文

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

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

尛丟丟 2025-01-10 11:57:47

您应该使用 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.

夕色琉璃 2025-01-10 11:57:47

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

Control.InvokeRequired

以下是有关Windows 窗体控件中的多线程的详细信息,其中包括以下示例使用后台线程。

The same InvokeRequired and Invoke (or BeginInvoke) should be used to set PictureBox.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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文