Я пытаюсь найти способ сделать потокобезопасную манипуляцию для позиционирования формы. Я создал поток, чтобы изменить положение формы, когда она отображается, и прервать ее, когда она не отображается. Это работает до тех пор, пока я не попытаюсь изменить положение. Я попытался поискать в Google потокобезопасный способ изменить положение окна, но не смог найти ничего, что работало бы достаточно хорошо.
Я проверил переполнение стека, но, возможно, не искал нужный поток. Я также искал Google с той же проблемой.
Form1 form;
IntPtr handle = FindWindow(null, WINDOW_NAME);
RECT rect;
Thread posThread;
public FormOverlay(Form1 _form) {
InitializeComponent();
form = _form;
posThread = new Thread(move);
}
private void FormOverlay_Load(object sender, EventArgs e) {
GetWindowRect(handle, out rect);
this.Size = new Size(rect.right - rect.left, rect.bottom - rect.top);
posThread.Start();
}
public struct RECT {
public int left, top, right, bottom;
}
public void move() {
while(form.isChecked()) { // Checkbox in another window
this.Top = rect.top;
this.Left = rect.left;
Thread.Sleep(100);
}
}
я получил
System.InvalidOperationException: 'Cross-thread operation not valid: Control 'FormOverlay' accessed from a thread other than the thread it was created on.
Thread Safe window positioning нет, вам нужно делать все это в основном потоке пользовательского интерфейса или маршалировать обратно к нему.
Спасибо @TheGeneral и Джон! Это решило мою проблему, в итоге код выглядел так: pastebin.com/BJk1xVPf





Не используйте цикл или потоки для решения этой проблемы, Winforms - это система, основанная на событиях, поэтому используйте ее в своих интересах. Событие Move будет вызвано при перемещении формы, и вы можете поместить туда свой код.
Вы также можете подписаться на CheckedChanged и запустить код перемещения, чтобы обновить позицию окна, когда поле изначально установлено.
public FormOverlay(Form1 _form) {
InitializeComponent();
form = _form;
form.SomeCheckbox.CheckedChanged += OnSomeCheckboxChanged
this.Move += OnMove;
}
private void FormOverlay_Load(object sender, EventArgs e) {
GetWindowRect(handle, out rect);
this.Size = new Size(rect.right - rect.left, rect.bottom - rect.top);
}
public struct RECT {
public int left, top, right, bottom;
}
private void OnSomeCheckboxChanged(object sender, System.EventArgs e) {
DoMove();
}
private void OnMove(object sender, System.EventArgs e) {
DoMove();
}
private void DoMove();
if (form.isChecked()) { // Checkbox in another window
this.Top = rect.top;
this.Left = rect.left;
}
}
Возможный дубликат Недопустимая межпоточная операция: доступ к элементу управления из потока, отличного от потока, в котором он был создан.