У меня есть длительная операция с пользовательским интерфейсом в моей форме, которая запускается всякий раз, когда происходит событие. Вместо того чтобы иметь блок пользовательского интерфейса во время выполнения операции, я бы хотел выполнить операцию в другом потоке, а также прервать этот поток и запустить его снова, если событие возникнет снова.
Однако, чтобы безопасно изменить элементы управления в моей форме, мне нужно использовать методы Invoke или BeginInvoke формы. Если я сделаю это, то смогу поместить все свои операции пользовательского интерфейса в одну функцию, подобную этой:
private delegate void DoUIStuffDelegate(Thing1 arg1, Thing2 arg2);
private void doUIStuff(Thing1 arg1, Thing2 arg2)
{
control1.Visible = false;
this.Controls.Add(arg1.ToButton());
...
control100.Text = arg2.ToString();
}
...
private void backgroundThread()
{
Thing1 arg1 = new Thing1();
Thing2 arg2 = new Thing2();
this.Invoke(new DoUIStuffDelegate(doUIStuff), arg1, arg2);
}
Thread uiStuffThread = null;
public void OnEventFired()
{
if (uiStuffThread != null)
uiStuffThread.Abort();
uiStuffThread = new Thread(backgroundThread);
uiStuffThread.Start();
}
но если я это сделаю, то потеряю преимущество работы в отдельном потоке. В качестве альтернативы я мог бы поместить их каждый в их собственную функцию, например:
private delegate void DoUIStuffLine1Delegate();
private delegate void DoUIStuffLine2Delegate(Thing1 arg1);
...
private delegate void DoUIStuffLine100Delegate(Thing2 arg2);
private void doUIStuffLine1()
{
control1.Visible = false;
}
private void doUIStuffLine2()
{
this.Controls.Add(arg1.ToButton());
}
...
private void doUIStuffLine100(Thing2 arg2)
{
control100.Text = arg2.ToString();
}
...
private void backgroundThread()
{
Thing1 arg1 = new Thing1();
Thing2 arg2 = new Thing2();
this.Invoke(new DoUIStuffLine1Delegate(doUIStuffLine1));
this.Invoke(new DoUIStuffLine2Delegate(doUIStuffLine2), arg1);
...
this.Invoke(new DoUIStuffLine100Delegate(doUIStuffLine100), arg2);
}
Thread uiStuffThread = null;
public void OnEventFired()
{
if (uiStuffThread != null)
uiStuffThread.Abort();
uiStuffThread = new Thread(backgroundThread);
uiStuffThread.Start();
}
но это ужасный, неразрешимый беспорядок. Есть ли способ создать поток, который может изменить пользовательский интерфейс, и который я могу прервать? Так что я могу сделать что-то вроде этого:
private void doUIStuff()
{
Thing1 arg1 = new Thing1();
Thing2 arg2 = new Thing2();
control1.Visible = false;
this.Controls.Add(arg1.ToButton());
...
control100.Text = arg2.ToString();
}
Thread uiStuffThread = null;
public void OnEventFired()
{
if (uiStuffThread != null)
uiStuffThread.Abort();
uiStuffThread = this.GetNiceThread(doUIStuff);
uiStuffThread.Start();
}
без необходимости отключения проверок между потоками в моей форме? В идеале я хотел бы иметь возможность установить какой-либо атрибут в потоке или метод, который по отдельности оборачивает все операции в делегатах, которые затем вызывались в потоке формы.