Мне нужно иметь возможность открывать несколько экземпляров одной и той же формы, так как мое приложение может быть использовано в разных местах одновременно. С другой стороны, мне нужно иметь возможность обрабатывать операции во время события «ОК» по одному за раз, чтобы гарантировать, что данные хранятся безопасно и не перезаписываются другим экземпляром формы случайно.Предоставление нескольких экземпляров формы, но обработка событий по одному
я показываю свою форму, используя метод .Show(), как я использую несколько делегатов в нем:
private void newToolStripMenuItem_Click(object sender, EventArgs e)
{
bookingForm = new BookingForm(AddMemberBooking, AddUserBooking, CloseBooking);
bookingForm.Show();
}
Я пытался использовать семафор, чтобы только одно событие кнопки OK нажата происходят одновременно, я объединил это с Thread для соответствия критериям, которые мне нужны.
Когда я нажимаю на кнопку «OK» Я даюсь следующее сообщение об ошибке:
Cross-thread operation not valid: Control 'comboBoxDay' accessed from a thread other than the thread it was created on.
Это код для моего бронирования класс формы:
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();
}
}
}
Я понимаю, что не может быть делая это наиболее эффективным способом, но время - это немного фактор. Я исследовал ошибку и слышал об использовании делегатов и .Invoke()
, но я все еще не совсем уверен, как это исправить.
EDIT:
Я нашел этот фрагмент кода при поиске исправления к моей проблеме. Я не понимаю, где/как я буду использовать его.
if(this.InvokeRequired)
{
this.Invoke(new MyEventHandler(this.CreateAForm()));
return;
}
EDIT2:
Кажется, что парень наконец-то увидел смысл, путем создания из с new
словами он явно проходит критерии. Хотел бы я знать это, прежде чем пытаться изобрести колесо.
Я вообще не хочу использовать нить, я знаю, что преимущества сильно зависят от того, подходит ли приложение для использования потоков, но, к сожалению, это часть критериев, которые мне нужно выполнить. Мне нужно разрешить открывать несколько форм бронирования, но только один может обрабатываться одновременно. Как работает операция .Invoke()? –
Threading * not * требуется одновременное открытие нескольких форм. Цикл сообщений Windows гарантирует, что все они останутся отзывчивыми. Сериализация обработки производится автоматически. –
Итак, можно ли предположить, что то, что я пытаюсь сделать просто «не должно»? –