0

我有一个带有控件的表单来显示一些自定义对象。在表单中,我订阅了一个事件 AddObject,该事件将对象从服务器传入时添加到 ToAdd 列表。我设置了一个计时器,每 10 秒运行一次,以将对象从 ToAdd 列表复制到显示列表(将项目批量添加到控件比在它们进入时一次添加 1 个更有效),它绑定到控制我的表单,然后我清除 ToAdd 列表。将锁放在 BeginInvoke 内部是否安全?有没有更好的方法来做到这一点?

        private System.Threading.Timer aTimer;
        private readonly Object sync = new Object();
        List<object> ToAdd = new List<object();
        List<object> Display = new List<object();

        private void Init()
        {
           TimerCallback tcb = IntermittentProcessMessages;
           aTimer = new System.Threading.Timer(tcb, null, 1000, 100);
           Server.MessageReceived += AddObject;   
        }

        private void AddObject(object t)
        {
            lock (sync)
            {
                try
                {
                   ToAdd.Add(t);
                }
                finally() {}
            }
         }


        private void IntermittentProcessMessages(object source)
        {
            try
            {
                if (this.IsHandleCreated == false)
                {
                    return;
                }
                this.BeginInvoke((Action)delegate()
                {
                   lock (sync)
                   {
                       if (ToAdd.Count > 0)
                       {
                           ToAdd.ForEach(f => Display.Add(f));
                           ToAdd.Clear();
                       }
                   }
                }
           }
           finally(){}
    }
4

1 回答 1

1

是的,它是安全的。从技术上讲,锁不在 . 中BeginInvoke,而是在从delegate.

一些注意事项:

  • List<T>有一种AddRange比 multiple 更有效的方法Add
    像这样使用它Display.AddRange(ToAdd);
  • 由于立即返回IntermittentProcessMessages,因此 try-catch 未覆盖in 的委托。BeginInvoke
于 2011-10-03T04:49:44.643 回答