2012-06-14 3 views
0

Я создаю повестку дня, которую можно использовать голосом. Кроме того, есть виртуальный помощник (VA), который дает обратную связь и имеет некоторый ИИ, чтобы получить хороший дневной ритм.C# изменение объекта из другой темы

Ситуация в том, что у меня есть публичная статическая повестка дня.

Повестка дня - это абстрактный класс, который в настоящее время имеет 9 различных типов Повестки. Это ядро ​​данных программы. Это содержит все, что должна знать программа.

Основная тема содержит GUI и удобство использования, которое люди могут ожидать с повесткой дня.

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

Сложная часть - это то, что я также хочу добавить к повестке дня некоторые логики (добавив AI так сказать), как ежедневное питание. Это происходит из потока VA, но я не могу изменить Agenda.agenda оттуда и получить сообщение об ошибке, заявив, что коллекция была изменена.

Я попытался заблокировать его, но нет никакой разницы.

добавления блюда на сегодня:

public void Meal() 
    { 
     DateTime date = DateTime.Now; 

     DateTime morning = date; 
     morning = morning.ChangeTime(8, 0, 0, 0); 

     DateTime afternoon = date; 
     afternoon = afternoon.ChangeTime(12, 0, 0, 0); 

     DateTime evening = date; 
     evening = evening.ChangeTime(16, 30, 0, 0); 

     if (!meal && date.Hour < 21) 
     { 
      if(date.DayOfWeek == DayOfWeek.Wednesday) 
       toAdd.Add(new Task("broodbuffet", morning, new Dictionary<DateTime, bool>())); 
      else 
       toAdd.Add(new Task("ontbijt", morning, new Dictionary<DateTime, bool>())); 
      toAdd.Add(new Task("lunch", afternoon, new Dictionary<DateTime, bool>())); 
      toAdd.Add(new Task("diner", evening, new Dictionary<DateTime, bool>())); 

      meal = true; 
     } 

     if (date.Hour > 22) 
      meal = false; 
    } 

в классе, где я делаю основы с моей VA:

ai.Meal(); 
UpdateAgenda(); 

метод обновления в теме:

private void UpdateAgenda() 
    { 
     if (ai.GetToAdd().Count != 0) 
     { 
      Agenda.agenda.AddRange(ai.GetToAdd()); 
     } 
    } 

и с блокировка:

private void UpdateAgenda() 
    { 
     if (ai.GetToAdd().Count != 0) 
     { 
      lock (Agenda.agenda) 
      { 
       Agenda.agenda.AddRange(ai.GetToAdd()); 
      } 
     } 
    } 

Итак, как добавить пункты повестки дня в мою повестку дня из VA-темы?

+0

Что делает 'ai.GetToAdd()' do? Я предполагаю, что он также выполняет итерацию через «Agenga.agenda», пока элементы добавляются. Но все еще не совсем ясно, что происходит в этом коде. Почему вы опубликовали метод «Meal»? Имеет ли это какое-либо отношение к вашей проблеме? – Groo

+0

Является ли ваш код чтения в потоке, который не добавляется, используя 'foreach'? На каком потоке возникает исключение? –

+0

Кроме того, несколько примечаний: 1. Я бы посоветовал использовать более значимые имена (например, если 'toAdd' был назван' tasks', было бы намного яснее, что он содержит список задач). 2. Синглтоны - зло, избегайте их. 3. Блокировка над экземпляром общедоступного объекта является плохой практикой, избегая ее.Повестка дня должна делать внутреннюю блокировку, если ее необходимо синхронизировать. 4. Если вы используете несколько потоков, вам следует избегать использования ненужных полей для хранения данных. Было бы намного лучше, если «Meal» вернет новый список, и вы просто напишете «AddToAgenda (Meal());». – Groo

ответ

0

Вы находитесь на правильном пути с блокировкой, но вы можете не только блокировать, когда вы меняете свойство.

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

0

В частности, полученная ошибка («Коллекция изменена»), возможно, вы перебираете любую коллекцию в объекте Agenda с помощью цикла foreach? Когда коллекция изменяется в пределах цикла foreach (в вашем случае, другим потоком), IEnumerator.MoveNext выбрасывает именно такую ​​ошибку. Если это проблема, вам необходимо заблокировать весь цикл foreach.

Смежные вопросы