C# 从其他线程更改对象

本文关键字:对象 线程 其他 | 更新日期: 2023-09-27 18:37:05

我正在创建一个可以通过语音使用的议程。此外,还有一个虚拟助手(VA)可以提供反馈,并有一些人工智能来获得并保持良好的日常节奏。

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

议程

是一个抽象类,目前有 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 线程添加到我的议程中?

C# 从其他线程更改对象

您在锁定方面走在正确的轨道上,但您不能只在更改属性时锁定。

锁不会锁定属性,而是锁定代码,

因此您必须在使用该属性的所有代码周围有一个锁,以便更改属性的代码可以锁定从属性读取的代码。

特别是对于您遇到的错误("集合已更改"),也许您使用 foreach 循环遍历 Agenda 对象中的任何集合?当集合在 foreach 循环中更改时(在您的情况下,由另一个线程更改),IEnumerator.MoveNext 会抛出这样的错误。如果这是问题所在,则需要锁定整个 foreach 循环。