Когда я пытаюсь изменить свойство UI (в частности, включить) мой поток бросает System.Threading.ThreadAbortExceptionДоступа к UI в потоке
Как получить доступ к UI в теме.
Когда я пытаюсь изменить свойство UI (в частности, включить) мой поток бросает System.Threading.ThreadAbortExceptionДоступа к UI в потоке
Как получить доступ к UI в теме.
Вы можете использовать BackgroundWorker, а затем изменить пользовательский интерфейс, как это:
control.Invoke((MethodInvoker)delegate {
control.Enabled = true;
});
Как насчет использования фона BackgroundWorker для Win Form вместо ручной синхронизации синхронизации aad?
Я предполагаю, что мы говорим о WinForms здесь? У вас должен быть один поток, управляющий этим - поток, который создал данный элемент управления. Если вы хотите сделать это из другого потока, который вы можете обнаружить с помощью Control.InvokeRequired, тогда вы должны использовать метод Control.Invoke для его сортировки на правильный поток. Google это свойство и метод (соответственно) для некоторых общих шаблонов при этом.
Вы можете безопасно использовать BeginInvoke(), а также в большинстве случаев, если вы не хотите маршировать любое заброшенное исключение обратно в вызывающий поток. – Quibblesome
'InvokeRequired/BeginInvoke' слишком многословен, IMO. –
Используйте SynchronizationContext
для перенаправления вызовов в поток пользовательского интерфейса, если вы хотите изменить пользовательский интерфейс, пока поток, отличный от UI, все еще работает. В противном случае используйте BackgroundWorker
.
void button1_Click(object sender, EventArgs e) {
var thread = new Thread(ParalelMethod);
thread.Start("hello world");
}
void ParalelMethod(object arg) {
if (this.InvokeRequired) {
Action<object> dlg = ParalelMethod;
this.Invoke(dlg, arg);
}
else {
this.button1.Text = arg.ToString();
}
}
Если вы используете C# 3.5, это очень легко использовать методы расширения и лямбды, чтобы предотвратить обновление пользовательского интерфейса от другие потоки.
public static class FormExtensions
{
public static void InvokeEx<T>(this T @this, Action<T> action) where T : Form
{
if (@this.InvokeRequired)
{
@this.Invoke(action, @this);
}
else
{
action(@this);
}
}
}
Итак, теперь вы можете использовать InvokeEx
в любой форме и быть в состоянии получить доступ к любым свойства/поля, которые не являются частью Form
.
this.InvokeEx(f => f.label1.Text = "Hello");
Абсолютно самый простой способ, с которым я столкнулся, и я попробовал множество обновлений пользовательских интерфейсов. Получил мой голос. – GONeale
Вы выигрываете за использование наименьшего количества текста и за отображение наиболее яркого примера/объяснения. Kudos – 2009-04-03 07:39:03
Спасибо, самый простой способ заглянуть в мое время. – Tirth