В моем приложении я запускаю скрытую dummyForm
, которая просто создается для отслеживания основного потока пользовательского интерфейса. Таким образом, если новая форма собирается быть созданной, InvokeRequired
используется в фиктивной форме, чтобы убедиться, что мы находимся в главном потоке пользовательского интерфейса при создании новой формы.
Сразу после создания формы frmStart
я проверяю frmStart.InvokeRequired
, и для него установлено значение false, поэтому здесь не нужно вызывать (то же самое относится и к dummyForm.InvokeRequired
).
Затем я получил frmMyDialog
, который будет использовать frmStart
в качестве родителя / владельца примерно так:
using(Create frmMyDialog on main UI thread)
{
frmMyDialog.Show(frmStart);
}
Это вызовет исключение перекрестной нити, и странная вещь в этом:
frmMyDialog.InvokeRequired = false
dummyForm.InvokeRequired = false
frmStart.InvokeRequired = true
И это даже когда я проверяю, что dummyForm.InvokeRequired
ложно при создании frmStart
?
Значение frmMyDialog.InvokeRequired
всегда должно совпадать с dummyForm.InvokeRequired
? Что здесь происходит?
Я проверил, что frmStart
и dummyForm
вообще не воссоздаются после создания первого экземпляра.
Редактировать1:
Вот как запускается приложение:
public static void Main(string[] args)
{
_instance = new MyClientMain(parameters);
Application.Run(_instance);
}
Конструктор класса MyClientMain запустит программу установки в статическом классе с именем MainControl. MainControler в методе установки создаст пустую форму следующим образом:
if (_dummyForm == null)
_dummyForm = new Form();
После того, как это будет сделано, форма входа будет обрабатывать вход в систему, и эта форма многопоточная. Когда вход в систему будет завершен, MainController будет вызван снова, чтобы создать экземпляр и открыть основной MDI windo, который содержит frmStart. Чтобы убедиться, что мы находимся в одном потоке, сделаем следующее:
public static StartApplication()
{
if (_dummyForm.InvokeRequired)
_dummyForm.Invoke(new MethodInvoker(delegate { OpenMainOrbitWindow(); }));
//Instanciate mainform and frmStart then open mainForm with frmStart as a MDI child
}
Здесь нет многопоточности.
Затем, когда служба переходит в автономный режим, запускается событие, и мне нужно вызвать frmMyDialog, но при использовании .ShowDialog () это диалоговое окно будет помещено за формами, так что родитель / владелец чаще всего будет найден и установлен так: *
public static Form GetActiveForm()
{
Form activeForm = Form.ActiveForm;
if (activeForm != null)
return activeForm;
if (MainOrbitForm.TopMost)
return MainOrbitForm;
else
{
FormCollection openForms = Application.OpenForms;
for (int i = 0; i < openForms.Count && activeForm == null; ++i)
{
Form openForm = openForms[i];
if (openForm.IsMdiContainer)
return openForm.ActiveMdiChild;
}
}
if (_patientForm != null)
{
if (_patientForm.TopMost)
return _patientForm;
}
return null;
}
public static string ShowOrbitDialogReName()
{
frmMyDialog myDialog;
Form testForm;
//Makes sures that the frmOrbitDialog is created with the same thread as the dummyForm
//InvokeRequired is used for this
using (myDialog = MainController.CreateForm<frmOrbitDialog>())
{
//Settings...
testForm = GetActiveForm();
myDialog.ShowDialog(GetActiveForm(testForm));
}
}
Проблема в том, что
myDialog.InvokeRequired = false
testForm.InvokeRequired = true;
MainController.DummyForm.InvokeRequired = false;
Edit2:
Запускаем и создаем dummyform:
dummyForm.InvokeRequired = false
Thread.CurrentThread.ManagedThreadId = 9
После успешного входа в систему мы создаем основную форму
_mainForm.InvokeRequired = false
MainControl.DummyForm.InvokeRequired = false
Thread.CurrentThread.ManagedThreadId = 9
Пока все выглядит хорошо. Затем принимается обратный вызов (WCF), и событие создает frmMyDialog в том же потоке (Invoke используется в dummyForm), а затем используется ShowDialog:
frmMyCustomDialog.ShowDialog(_mainForm)
Это создает исключение CrossThreadException, и вот так оно выглядит на данный момент:
_mainForm.InvokeRequired = true
frmMyCustomDialog.InvokeRequired = false
MainControl.DummyForm.InvokeRequired = false
Thread.CurrentThread.ManagedThreadId = 12
Почему MainControl.DummyForm не соответствует действительности? ManageThreadId не 9, а 12?