private void Add(NetworkTask task)
 {
     lock (_lock)
     {
         if (_state == STATE.STARTED)
         {
             _networkTasks.Enqueue(task);
         }
     }
 }
        // Producer Task
        // 主要任務是到資料庫查看有哪些公告訊息未發佈的,如果有未發佈的公告訊息,
        // 從資料庫找出那些公告訊息應發佈到哪些裝置,並排程網路任務 (NetworkTask)。
        private void PublishAnnouncementsTask(CancellationToken cancelToken)
        {
            try
            {
                int lastestPublishedAnnouncementID = 0;

                while (true)
                {
                    _token.ThrowIfCancellationRequested();

                    using (var db = new ICMDBContext())
                    {
                        try
                        {
                            var latestGeneratedAnnouncementID = db.Announcements.Select(a => a.id).DefaultIfEmpty(0).Max();
                            if (latestGeneratedAnnouncementID != lastestPublishedAnnouncementID)
                            {
                                var devices = (from device in db.Devices
                                               from ar in db.AnnouncementRooms
                                               where device.roomid.StartsWith(ar.RoomID) &&
                                               ar.AnnouncementID > lastestPublishedAnnouncementID
                                               select device).Distinct();
                                foreach (var device in devices)
                                {
                                    if (device.type == (int)DeviceType.Indoor_Phone ||
                                        device.type == (int)DeviceType.Indoor_Phone_SD)
                                    {
                                        NetworkTask task = new NetworkTask
                                        {
                                            IP       = device.ip,
                                            TaskFunc = async() =>
                                            {
                                                int newAnnouncementCount = await Task.Run(() =>
                                                {
                                                    int count = 0;
                                                    try
                                                    {
                                                        using (var _db = new ICMDBContext())
                                                        {
                                                            count = (from ar in _db.AnnouncementRooms
                                                                     where ar.RoomID == device.roomid.Substring(0, 14) &&
                                                                     ar.HasRead == false
                                                                     select ar).Count();
                                                        }
                                                    }
                                                    catch (Exception) { }
                                                    return(count);
                                                }).ConfigureAwait(false);

                                                await HttpClient.SendNewTextMsgCountAsync(device.ip, newAnnouncementCount).ConfigureAwait(false);
                                            }
                                        };
                                        this.Add(task);
                                        //DebugLog.TraceMessage(string.Format("IP: {0}", device.ip));
                                    }
                                }
                                lastestPublishedAnnouncementID = latestGeneratedAnnouncementID;
                            }
                        }
                        catch (Exception) { }
                    }
                    Thread.Sleep(100);
                }
            }
            catch (OperationCanceledException) { }
        }