protected void SaveItems(SaveMetrics metrics)
        {
            Dictionary <Serial, Item> items = World.Items;

            GenericWriter idx;
            GenericWriter tdb;
            GenericWriter bin;

            if (UseSequentialWriters)
            {
                idx = new BinaryFileWriter(World.ItemIndexPath, false);
                tdb = new BinaryFileWriter(World.ItemTypesPath, false);
                bin = new BinaryFileWriter(World.ItemDataPath, true);
            }
            else
            {
                idx = new AsyncWriter(World.ItemIndexPath, false);
                tdb = new AsyncWriter(World.ItemTypesPath, false);
                bin = new AsyncWriter(World.ItemDataPath, true);
            }

            idx.Write((int)items.Count);

            DateTime n = DateTime.UtcNow;

            foreach (Item item in items.Values)
            {
                if (item.Decays && item.Parent == null && item.Map != Map.Internal && (item.LastMoved + item.DecayTime) <= n)
                {
                    _decayQueue.Enqueue(item);
                }

                long start = bin.Position;

                idx.Write((int)item._TypeRef);
                idx.Write((int)item.Serial);
                idx.Write((long)start);

                item.Serialize(bin);

                if (metrics != null)
                {
                    metrics.OnItemSaved((int)(bin.Position - start));
                }

                idx.Write((int)(bin.Position - start));

                item.FreeCache();
            }

            tdb.Write((int)World._ItemTypes.Count);
            for (int i = 0; i < World._ItemTypes.Count; ++i)
            {
                tdb.Write(World._ItemTypes[i].FullName);
            }

            idx.Close();
            tdb.Close();
            bin.Close();
        }
        private Task SaveItems()
        {
            //Start the blocking consumer; this runs in background.
            Task commitTask = StartCommitTask(_itemThreadWriters, _itemData, _itemIndex);

            IEnumerable <Item> items = World.Items.Values;

            //Start the producer.
            Parallel.ForEach(items, () => new QueuedMemoryWriter(),
                             (Item item, ParallelLoopState state, QueuedMemoryWriter writer) =>
            {
                long startPosition = writer.Position;

                item.Serialize(writer);

                int size = (int)(writer.Position - startPosition);

                writer.QueueForIndex(item, size);

                if (item.Decays && item.Parent == null && item.Map != Map.Internal && DateTime.UtcNow > (item.LastMoved + item.DecayTime))
                {
                    _decayBag.Add(item);
                }

                if (_metrics != null)
                {
                    _metrics.OnItemSaved(size);
                }

                return(writer);
            },
                             (writer) =>
            {
                writer.Flush();

                _itemThreadWriters.Add(writer);
            });

            _itemThreadWriters.CompleteAdding();    //We only get here after the Parallel.ForEach completes.  Lets our task

            return(commitTask);
        }