Je dois pouvoir laisser plusieurs instances du même formulaire ouvertes car mon application peut être utilisée à différents endroits à la fois. D'un autre côté, je dois être en mesure de traiter les opérations pendant l'événement "OK" une à la fois pour assurer que les données sont stockées en toute sécurité et ne sont pas écrasées par une autre instance de formulaire par accident.Fournir plusieurs instances d'un formulaire mais traiter les événements un à la fois
Je montre ma forme en utilisant la méthode .Show() que j'utilise quelques délégués en elle:
private void newToolStripMenuItem_Click(object sender, EventArgs e)
{
bookingForm = new BookingForm(AddMemberBooking, AddUserBooking, CloseBooking);
bookingForm.Show();
}
J'ai essayé d'utiliser le mutex pour permettre un seul événement du bouton OK est appuyé arriver à la fois, j'ai combiné cela avec un fil pour répondre aux critères dont j'ai besoin.
Lorsque je clique sur le bouton « OK » on me donne l'erreur suivante:
Cross-thread operation not valid: Control 'comboBoxDay' accessed from a thread other than the thread it was created on.
C'est le code pour mon formulaire de réservation classe:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace Collection
{
//Allows the class to be serialized
[Serializable()]
public delegate void AddMemberBookingMethod(int date, int time, int mNo);
public delegate void AddUserBookingMethod(int date, int time, string fName, string lName, string pCode);
public delegate void CloseBookingFormMethod();
public partial class BookingForm : Form
{
public CloseBookingFormMethod CloseBookingForm;
public AddMemberBookingMethod AddMemberBooking;
public AddUserBookingMethod AddUserBooking;
private Mutex bookingMut = new Mutex();
private Thread thread;
public bool IsUser;
public BookingForm(AddMemberBookingMethod ambm, AddUserBookingMethod aubm, CloseBookingFormMethod cbfm)
{
InitializeComponent();
AddMemberBooking = ambm;
AddUserBooking = aubm;
CloseBookingForm = cbfm;
checkBoxMember.Checked = true;
//Control.CheckForIllegalCrossThreadCalls = false;
}
private void checkBoxUser_CheckedChanged(object sender, EventArgs e)
{
if (checkBoxUser.Checked)
{
IsUser = true;
checkBoxMember.CheckState = CheckState.Unchecked;
textBoxMNo.Enabled = false;
textBoxFName.Enabled = true;
textBoxLName.Enabled = true;
textBoxPCode.Enabled = true;
}
else
{
IsUser = false;
checkBoxMember.CheckState = CheckState.Checked;
textBoxMNo.Enabled = true;
textBoxFName.Enabled = false;
textBoxLName.Enabled = false;
textBoxPCode.Enabled = false;
}
}
private void checkBoxMember_CheckedChanged(object sender, EventArgs e)
{
if (checkBoxMember.Checked)
{
IsUser = false;
checkBoxUser.CheckState = CheckState.Unchecked;
textBoxFName.Enabled = false;
textBoxLName.Enabled = false;
textBoxPCode.Enabled = false;
}
else
{
IsUser = true;
checkBoxUser.CheckState = CheckState.Checked;
textBoxMNo.Enabled = false;
textBoxFName.Enabled = true;
textBoxLName.Enabled = true;
textBoxPCode.Enabled = true;
}
}
private void buttonOK_Click(object sender, EventArgs e)
{
this.thread = new Thread(new ThreadStart(MakeBooking));
this.thread.Name = "bookingThread";
this.thread.Start();
}
private void MakeBooking()
{
this.bookingMut.WaitOne();
int date = this.comboBoxDay.SelectedIndex;
int time = this.comboBoxTime.SelectedIndex;
if (IsUser)
{
string fName = textBoxFName.Text;
string lName = textBoxLName.Text;
string pCode = textBoxPCode.Text;
AddUserBooking(date, time, fName, lName, pCode);
}
else
{
int mNo = int.Parse(textBoxMNo.Text);
AddMemberBooking(date, time, mNo);
}
this.bookingMut.ReleaseMutex();
CloseBookingForm();
}
private void buttonClose_Click(object sender, EventArgs e)
{
CloseBookingForm();
}
}
}
Je me rends compte que je ne peux pas être le faire de la manière la plus efficace, mais le temps est un facteur. J'ai étudié l'erreur et j'ai entendu parler de l'utilisation de délégués et .Invoke()
mais je ne suis toujours pas tout à fait sûr de savoir comment y remédier.
EDIT:
J'ai trouvé cet extrait de code lors de la recherche d'une solution à mon problème. Je ne comprends pas où/comment je l'utiliserais.
if(this.InvokeRequired)
{
this.Invoke(new MyEventHandler(this.CreateAForm()));
return;
}
EDIT2:
Semble le gars a vu enfin le sens, en créant le mot de la new
passe apparemment les critères. J'aurais aimé le savoir avant d'essayer de réinventer la roue.
Je ne veux pas utiliser de thread du tout, je sais que les avantages dépendent fortement de savoir si l'application est adaptée pour utiliser le filetage, mais malheureusement, c'est une partie des critères que je dois respecter. Je dois pouvoir autoriser l'ouverture de plusieurs formulaires de réservation, mais un seul peut être traité à la fois. Comment l'opération .Invoke() fonctionne-t-elle exactement? –
Il n'est pas obligatoire d'avoir plusieurs formulaires en même temps. La boucle de messages Windows garantit que tous restent réactifs. La sérialisation du traitement est automatique. –
Donc, est-il sûr de supposer que ce que j'essaie de faire simplement "ne devrait pas" être fait? –