Крест-нарезка

88
8

В настоящее время я пытаюсь создать таймер, который будет запускать кусок кода каждые несколько миллисекунд. проблема заключается в том, что я хочу, чтобы Модифицировать положение окна изображения, которое создано в том же потоке, что и таймер, я получаю ошибку объекта 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;
}
}


В надежде, что мне не нужно вызывать каждый элемент управления, который я объявляю в этом потоке, поскольку план должен был сделать список ящиков с картинками, чтобы пользователь мог добавлять ящики для изображений по мере необходимости.


Спасибо за помощь.

спросил(а) 2021-01-25T17:21:06+03:00 4 месяца, 2 недели назад
1
Решение
89

Вместо создания собственного потока вы должны использовать System.Windows.Forms.Timer.

Таким образом, everthying уже будет в потоке пользовательского интерфейса.

ответил(а) 2021-01-25T17:21:06+03:00 4 месяца, 2 недели назад
63

Для установки PictureBox.Location следует использовать те же InvokeRequired и Invoke (или BeginInvoke). Свойства управления должны быть заданы в потоке, где был создан дескриптор управления, который определяется WinForms, а не там, где сам элемент управления был создан.


Причины объясняются в Control.InvokeRequired.

Подробнее о многопоточности в Windows Forms Controls, который включает пример использования фонового потока.

ответил(а) 2021-01-25T17:21:06+03:00 4 месяца, 2 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема