Любое решение для исключения Illegal Cross Thread Operation?

При привязке данных в C# поток, изменяющий данные, также вызывает изменение элемента управления. Но если этот поток не тот, в котором был создан элемент управления, вы получите исключение Illegal Cross Thread Operation.

Есть ли способ предотвратить это?

Ответов (4)

В WPF и Silverlight инфраструктура привязки обеспечивает переключение на поток пользовательского интерфейса.

Поскольку у меня нет тестового примера, я не могу гарантировать это решение, но мне кажется, что здесь подойдет сценарий, аналогичный тому, который используется для обновления индикаторов выполнения в разных потоках (используйте делегат).

public delegate void DataBindDelegate();
public DataBindDelegate BindData = new DataBindDelegate(DoDataBind);

public void DoDataBind()
{
    DataBind();
}

Если привязка данных должна выполняться определенным потоком, позвольте этому потоку выполнять работу!

Если вызов потока является «незаконным» (то есть вызов DataBind влияет на элементы управления, которые не были созданы в потоке, из которого он вызывается), вам необходимо создать делегат, чтобы даже если решение / подготовка для DataBind не выполнялись в поток, создающий элемент управления, любая их результирующая модификация (например, DataBind ()) будет.

Вы бы вызывали мой код из рабочего потока следующим образом:

this.BindData.Invoke();

Это приведет к тому, что исходный поток выполнит привязку, которая (при условии, что это поток, создавший элементы управления) должен работать.

Вы должны уметь делать что-то вроде:

if (control.InvokeRequired)
{
    control.Invoke(delegateWithMyCode);
}
else
{
    delegateWithMyCode();
}

InvokeRequired - это свойство в элементах управления, чтобы увидеть, находитесь ли вы в правильном потоке, тогда Invoke вызовет делегат в правильном потоке.

ОБНОВЛЕНИЕ: Собственно, на моей последней работе мы сделали что-то вроде этого:

private void SomeEventHandler(Object someParam)
{
    if (this.InvokeRequired)
    {
        this.Invoke(new SomeEventHandlerDelegate(SomeEventHandler), someParam);
    }

    // Regular handling code
}

что устраняет необходимость в блоке else и как бы ужесточает код.