Очереди Обновления ObservableCollection - PullRequest
2 голосов
/ 17 октября 2011

Я программирую приложение TAPI, которое использует шаблон состояний для работы с различными состояниями, в которых может находиться ТЗ. Входящие и исходящие вызовы записываются через ObservableCollection в ListView (журнал вызовов).Данные вызова сравниваются с контактами, хранящимися в базе данных SQL-Server, для определения возможных совпадений.Эта информация затем используется для обновления журнала вызовов.Конечно, все это в режиме реального времени и все в / в различных состояниях FSM (конечный автомат).

Чтобы различать звонки, я использую идентификатор звонка (который предоставляется TAPI).Когда телефон звонит или я начинаю звонить, новая запись, включая ее идентификатор вызова, добавляется в журнал вызовов, и в базе данных клиентов выполняется поиск номера, и определенные данные в журнале соответствующим образом обновляются.При прохождении через различные состояния вызова приложение динамически обновляет журнал (т.е. изменяет значок, который визуально показывает состояние конкретного вызова и т. Д.).

Именно эти обновления ObservableCollection вызывают у меня головную боль,так как они должны происходить в определенном порядке.Например, при получении вызова связанное состояние создаст новую запись в ObservableCollection.Когда состояние изменяется, новое состояние может попытаться обновить коллекцию, даже если не ясно, какая запись должна быть изменена, уже добавлена.Состояния переключаются очень быстро, по-видимому, быстрее, чем может происходить обновление коллекции.

Будет ли какая-то очередь сообщений возможной / хорошим решением?Если да, то как можно реализовать такую ​​очередь сообщений - в контексте конечного автомата или ObservableCollection.Я не ищу полных решений, но любая информация, которую я не могу легко найти через google или stackoverflow, была бы признательна.

Редактировать : значительно перефразировать вопрос.

Редактировать : Я добавил собственное решение проблемы, но подожду и посмотрю, найдется ли кто-нибудь с лучшей идеей.

Ответы [ 2 ]

1 голос
/ 20 октября 2011

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

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

Таким образом, в основном: все события TAPI ( invoker ) добавляются в очередь ( клиент ) в том порядке, в котором они происходят, как можно быстрее. Затем очередь передает информацию TAPI на получатель , конечный автомат, выполняющий бизнес-логику, не торопясь, но следя за тем, чтобы информация обновлялась в правильном порядке.

Редактировать: Начиная с .NET 4.0, вы можете использовать Класс ConcurrentQueue (T) для достижения того же результата.

1 голос
/ 17 октября 2011

Вы проверили, является ли результат FirstOrDefault null? Это может произойти, если в коллекции нет элемента с данным id.

Например:

var element = this.FirstOrDefault(p => p.ID == id);
if (element != null) {
    // Do something with element.Number.
}

Или вы можете просто позвонить First и посмотреть, получите ли вы InvalidOperationException.

--- РЕДАКТИРОВАТЬ ---

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

"Ни один из членов экземпляра не гарантированно является потокобезопасным."

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

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