2012-06-14 63 views
0

我正在创建一个可以通过语音使用的议程。 此外还有一位虚拟助理(VA),他提供反馈,并有一些AI来保持良好的日常节奏。C#从其他线程更改对象

情况是我有一个公共静态列表议程。

议程是一个抽象类,它目前有9种不同的议程类型。 这是程序的数据核心。这包含了程序需要知道的一切。

主线程包含图形用户界面和人们可能期待的可用性。

虚拟助手需要做的所有事情都是在不同的线程中完成。这主要是检查议程,并提出一些问题,如果人们想要在议程中做任何事情。

棘手的部分是,当我还想从某些逻辑(比如说增加人工智能等)中添加事物到日程表时,就像每日餐食一样。这来自VA线程,但我无法从那里更改Agenda.agenda并出现错误,并说该集合已被修改。

我试过锁定它,但没有区别。在课堂上,我做的基本知识与我的VA

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; 
    } 

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循环。