Коллекция наблюдений (Bind To Datagid) - ошибка потоков - PullRequest
1 голос
/ 08 ноября 2011

У меня есть следующие настройки:

public class Monitor
{
    public ObservableCollection<People> listOfPeople = new ObservableCollection<People>();


    public dosomework() {
        Thread t = new ThreadStart(longwork);
        t.Start();
    }

   public longwork() {
        listOfPeople.Add(new People());
        Thread.Sleep(10000);

   }

}

public class People : INotifyPropertyChanged
{
    int _age;
    public int Age
    {
        get { return _age; }
        set
        {
            _age = value;
            Notify("Age");
        }
    }
}

public class UI : Window
{
    Monitor md = new Monitor();
}

Я хочу связать сетку данных с наблюдаемой коллекцией (datagrid.ItemSource = md.listOfPeople), однако я получаю ошибку потокаКроме того, если я не выполняю долгую работу над новым потоком, пользовательский интерфейс обновляется только после завершения функции longwork.Я думал, что связывание позволит избежать этой проблемы.

Любая помощь приветствуется.

Ответы [ 3 ]

1 голос
/ 09 ноября 2011

Как уже упоминалось другими, если вы выполняете какую-либо работу с потоком, отличным от пользовательского интерфейса, вы должны отправить потоку пользовательского интерфейса, чтобы фактически обновить любой элемент, связанный с элементом пользовательского интерфейса.

В вашем примере это было бы довольно просто. Просто передайте Dispatcher ( msdn ) вашего окна вашему Monitor и используйте его для соответствующей отправки:

...
Monitor md = new Monitor(this.Dispatcher);
...
public Monitor(Dispatcher dispatcher)
{
     _dispatcher = dispatcher;
}
...
public longwork() {
    _dispatcher.BeginInvoke((Action)(()=>listOfPeople.Add(new People()));
    Thread.Sleep(10000);

}

Вы можете позвонить Dispatcher.Invoke вместо Dispatcher.BeginInvoke, но если вас не интересует исход и вы хотите быстро двигаться дальше, BeginInvoke ваш друг.

1 голос
/ 08 ноября 2011

Связывание - это просто «другой код, слушающий изменения», поэтому многопоточность все еще остается проблемой.

Обычное исправление заключается в добавлении в список в потоке пользовательского интерфейса, так как именно там Grid будет прослушивать, но это приведет к низкой производительности при запуске для отдельных элементов.

Лучше всего пакетировать дополнения во временный список, работающий в фоновом потоке, и вызывать AddRange через интервалы (каждые 100 элементов?), Чтобы переместить этот пакет в коллекцию пользовательского интерфейса, чтобы дать лучший ответ и регулярное обновление DataGrid.

0 голосов
/ 08 ноября 2011

Сетка данных с привязкой к данным подписана на событие CollectionChanged. По моему опыту, событие CollectionChanged возникает в любом потоке, который вызвал изменение коллекции. В этом случае это не поток пользовательского интерфейса. Поскольку элементы пользовательского интерфейса можно изменять только из потока пользовательского интерфейса, а событие вызывается и обрабатывается в потоке, не являющемся пользовательским интерфейсом, вы получите сообщение об ошибке в потоке.

Как указано выше, простое решение состоит в изменении только ObservableCollection из потока пользовательского интерфейса.

Если вы используете WPF или Silverlight, все FrameworkElements имеют свойство Dispatcher, которое вы можете использовать для выполнения работы в потоке пользовательского интерфейса. Смотрите также: http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcherobject.aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...