2012-06-14 2 views
0

음성으로 사용할 수있는 의제를 만들고 있습니다. 또한 피드백을 제공하고 좋은 일일 리듬을 유지하기위한 인공 지능을 가진 가상 조수 (VA)가 있습니다.C# 다른 스레드에서 개체 변경

상황에 따라 공개 정적 목록 아젠다가 있습니다.

아젠다는 현재 9 가지 아젠다 유형이있는 추상 클래스입니다. 이것은 programm의 데이터 코어입니다. 이것은 프로그램이 알아야 할 모든 것을 포함합니다.

메인 스레드에는 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()'의 기능은 무엇입니까? 나는 아이템이 추가되는 동안 'Agenga.agenda'를 반복하는 것으로 추정하고 있습니다. 그러나이 코드에서 어떤 일이 벌어지고 있는지는 아직 명확하지 않습니다. '식사 '방법을 게시 한 이유는 무엇입니까? 그것은 당신의 문제와 관련이 있습니까? – Groo

+0

'foreach'를 사용하여 추가하지 않은 스레드의 읽기 코드가 있습니까? 어떤 스레드에서 예외가 발생합니까? –

+0

또 하나, 몇 가지주의 사항 : 1. 더 의미있는 이름을 사용하는 것이 좋습니다 (예를 들어,'toAdd'가'tasks'라는 이름이 붙은 경우, 작업 목록이 포함되어 있다는 것이 훨씬 명확합니다). 2. 싱글턴은 사악하고 피한다. 3. 공용 객체 인스턴스를 잠그는 것은 나쁜 습관입니다.의제는 동기화가 필요한 경우 모든 잠금을 내부적으로 수행해야합니다. 4. 다중 스레드를 사용하는 경우 데이터 저장에 불필요한 필드를 사용하지 마십시오. 'Meal'이 새로운 목록을 반환한다면'AddToAgenda (Meal()); '라고 쓰면 훨씬 좋을 것입니다. – Groo

답변

0

잠금 기능이 제대로 작동하지만 속성을 변경하면 잠글 수 없습니다.

잠금이 속성을 잠그지 않고 코드를 잠그므로 특성을 변경하는 코드가 읽는 코드를 잠글 수 있도록 모두 코드를 사용하는 코드를 잠글 필요가 있습니다. 재산에서.

0

특히 ("변경된 컬렉션") 오류가 발생했을 때 foreach 루프를 사용하여 Agenda 개체의 컬렉션을 반복 할 수 있습니까? 컬렉션이 foreach 루프 내에서 (다른 스레드에 의해) 변경되면 IEnumerator.MoveNext는 정확하게 이러한 오류를 발생시킵니다. 이 문제가 발생하면 전체 foreach 루프를 잠글 필요가 있습니다.

관련 문제