si j'appelle form.show()
sur un objet WinForms à partir d'un autre thread, le formulaire lève une exception. Est-il possible d'ajouter un nouveau formulaire visible au fil principal de l'application? Sinon, comment puis-je ouvrir le formulaire sans arrêter mon thread en cours d'exécution?
Voici mon exemple de code. J'essaie de démarrer un fil, puis d'exécuter certains travaux au sein de ce fil. Au fur et à mesure que le travail avance, je montrerai le formulaire.
public void Main()
{
new Thread(new ThreadStart(showForm)).Start();
// Rest of main thread goes here...
}
public void showForm()
{
// Do some work here.
myForm form = new myForm();
form.Text = "my text";
form.Show();
// Do some more work here
}
Essayez d'utiliser un appel d'invocation:
public static Form globalForm;
void Main()
{
globalForm = new Form();
globalForm.Show();
globalForm.Hide();
// Spawn threads here
}
void ThreadProc()
{
myForm form = new myForm();
globalForm.Invoke((MethodInvoker)delegate() {
form.Text = "my text";
form.Show();
});
}
L'appel "invoke" indique le formulaire "Veuillez exécuter ce code dans votre fil plutôt que le mien". Vous pouvez ensuite apporter des modifications à l'interface utilisateur WinForms à partir du délégué.
Plus de documentation sur Invoke est ici: http://msdn.Microsoft.com/en-us/library/zyzhdc6b.aspx
EDIT: Vous devez utiliser un objet WinForms qui existe déjà pour appeler invoke. J'ai montré ici comment créer un objet global. sinon, si vous avez d'autres objets Windows, ceux-ci fonctionneront également.
Vous devez appeler Application.Run()
après avoir appelé form.Show()
. Par exemple:
public void showForm()
{
// Do some work here.
myForm form = new myForm();
form.Text = "my text";
form.Show();
Application.Run();
// Do some more work here
}
En ce qui concerne les détails derrière pourquoi, ce message msdn peut aider.
Le meilleur moyen par mon expérience:
var ac = (ReportPre)Application.OpenForms["ReportPre"];
Thread shower = new Thread(new ThreadStart(() =>
{
if (ac == null)
{
this.Invoke((MethodInvoker)delegate () {
ac = new ReportPre();
ac.Show();
});
}
else
{
this.Invoke((MethodInvoker)delegate
{
pictureBox1.Visible = true;
});
if (ac.InvokeRequired)
{
ac.Invoke(new MethodInvoker(delegate {
ac.Hide();
ac.Show();
}));
}
}
}));
shower.Start();