Пример #1
0
        public void Tests()
        {
            var cache = new LRUCache <int, int>(3);

            Assert.AreEqual(0, cache.Count);
            cache.Set(1, 10);
            Assert.AreEqual(1, cache.Count);
            cache.Set(2, 20);
            Assert.AreEqual(2, cache.Count);
            cache.Set(3, 30);
            Assert.AreEqual(3, cache.Count);
            Assert.AreEqual(10, cache[1]);
            Assert.AreEqual(20, cache[2]);
            Assert.AreEqual(30, cache[3]);

            cache.Set(4, 40);
            Assert.IsFalse(cache.ContainsKey(1));
            Assert.AreEqual(40, cache[4]);
            Assert.AreEqual(3, cache.Count);

            cache[4] = 400;
            Assert.AreEqual(400, cache[4]);

            cache[2] = 200;
            Assert.AreEqual(200, cache[2]);
            cache[3] = 300;
            Assert.AreEqual(300, cache[3]);

            cache.Set(1, 10);
            Assert.IsFalse(cache.ContainsKey(4));

            cache.Clear();
            Assert.AreEqual(0, cache.Count);
            Assert.IsFalse(cache.ContainsKey(1));
        }
Пример #2
0
        public void LRUCache_Basic()
        {
            LRUCache <string, string> cache;
            string value;

            cache = new LRUCache <string, string>(StringComparer.OrdinalIgnoreCase);
            Assert.AreEqual(0, cache.Count);

            cache.Add("foo", "bar");
            Assert.AreEqual(1, cache.Count);
            Assert.AreEqual("bar", cache["foo"]);

            try
            {
                value = cache["xxx"];
                Assert.Fail("Expected a KeyNotFoundException");
            }
            catch (Exception e)
            {
                Assert.AreEqual(typeof(KeyNotFoundException).Name, e.GetType().Name);
            }

            cache["foo"] = "foobar";
            Assert.AreEqual("foobar", cache["foo"]);

            cache["bar"] = "boobar";
            Assert.AreEqual("boobar", cache["bar"]);
            Assert.AreEqual("foobar", cache["foo"]);

            Assert.IsTrue(cache.TryGetValue("foo", out value));
            Assert.AreEqual("foobar", value);
            Assert.IsTrue(cache.TryGetValue("bar", out value));
            Assert.AreEqual("boobar", value);
            Assert.IsFalse(cache.TryGetValue("xxx", out value));

            Assert.IsTrue(cache.ContainsKey("foo"));
            Assert.IsTrue(cache.ContainsKey("bar"));
            Assert.IsFalse(cache.ContainsKey("xxx"));

            cache.Remove("foo");
            Assert.IsFalse(cache.ContainsKey("foo"));

            cache.Remove("bar");
            Assert.IsFalse(cache.ContainsKey("bar"));

            cache.Remove("xxx");
            Assert.IsFalse(cache.ContainsKey("xxx"));

            cache["foo"] = "foobar";
            cache["bar"] = "boobar";
            Assert.AreEqual(2, cache.Count);
            Assert.IsTrue(cache.ContainsKey("foo"));
            Assert.IsTrue(cache.ContainsKey("bar"));
            cache.Clear();
            Assert.AreEqual(0, cache.Count);
            Assert.IsFalse(cache.ContainsKey("foo"));
            Assert.IsFalse(cache.ContainsKey("bar"));
        }
Пример #3
0
        public void TestContainsKey()
        {
            LRUCache <String, String> underTest = new LRUCache <String, String>(666);

            underTest.Add("key1", "value");
            underTest.Add("key2", "value");
            underTest.Add("key3", "value");
            Assert.That(underTest.Count == 3);
            Assert.That(underTest.ContainsKey("key2"));
            Assert.That(underTest.ContainsKey("key1"));
            Assert.That(underTest.ContainsKey("key3"));
            Assert.IsFalse(underTest.ContainsKey("Key4"));
        }
Пример #4
0
 private void DrawVisibleChunk(Vector3Int observerPosition, bool drawLater)
 {
     for (int layer = layerBottom; layer <= layerTop; layer++)
     {
         for (int col = -2; col <= 2; col++)
         {
             for (int row = -2; row <= 2; row++)
             {
                 Vector3Int c = new Vector3Int(row + observerPosition.x, col + observerPosition.y, layer);
                 if (!chunkCache.ContainsKey(c))
                 {
                     if (drawLater)
                     {
                         DrawChunkLater(c);
                     }
                     else
                     {
                         DrawChunk(c);
                     }
                 }
                 else
                 {
                     chunkCache.Refresh(c);
                 }
             }
         }
     }
 }
Пример #5
0
        public void TestResize()
        {
            LRUCache <Int64, Int64> underTest = new LRUCache <Int64, Int64>(1000);

            Int64 count = new Int64();
            long  max   = 0;

            for (; count < 27276827; count++)
            {
                long start = DateTime.Now.Ticks;
                if (!underTest.ContainsKey(count))
                {
                    underTest.Add(count, count);
                }
                long duration = DateTime.Now.Ticks - start;
                if (duration > max)
                {
                    Tracer.Debug("count: " + count + ", new max=" + duration);
                    max = duration;
                }
                if (count % 100000000 == 0)
                {
                    Tracer.Debug("count: " + count + ", max=" + max);
                }
            }

            Assert.AreEqual(1000, underTest.Count, "size is still in order");
        }
Пример #6
0
        public static string KerbalName(ProtoCrewMember.Gender gender)
        {
            string defaultKerbalName = "";

            do
            {
                defaultKerbalName = CrewGenerator.GetRandomName(gender, random);
            }while (nameCache.ContainsKey(defaultKerbalName));

            string kerbalName = "";

            do
            {
                kerbalName = DraftTwitchViewers.KerbalName(defaultKerbalName);
            }while (nameCache.ContainsKey(kerbalName));

            nameCache.Add(kerbalName, 0);
            return(kerbalName);
        }
Пример #7
0
        private void InitKey(string method, string password)
        {
            method  = method.ToLower();
            _method = method;
            string k = method + ":" + password;

            ciphers       = getCiphers();
            _cipherInfo   = ciphers[_method];
            _innerLibName = string.IsNullOrWhiteSpace(_cipherInfo.name) ? method : _cipherInfo.name;
            _cipher       = _cipherInfo.type;
            if (_cipher == 0)
            {
                throw new Exception("method not found");
            }
            keyLen = ciphers[_method].key_size;
            ivLen  = ciphers[_method].iv_size;
            if (!CachedKeys.ContainsKey(k))
            {
                lock (CachedKeys)
                {
                    if (!CachedKeys.ContainsKey(k))
                    {
                        byte[] passbuf = Encoding.UTF8.GetBytes(password);
                        _key = new byte[32];
                        byte[] iv = new byte[16];
                        bytesToKey(passbuf, _key);
                        CachedKeys.Set(k, _key);
                        CachedKeys.Sweep();
                    }
                }
            }
            if (_key == null)
            {
                _key = CachedKeys.Get(k);
            }
            Array.Resize(ref _iv, ivLen);
            randBytes(_iv, ivLen);
        }
Пример #8
0
        public static void TestGetValue()
        {
            var cache = new LRUCache <string, int>(3);

            cache["a"] = 1;
            cache["b"] = 2;
            cache["c"] = 3;
            cache["d"] = 4;

            Assert.IsFalse(cache.ContainsKey("a"));
            Assert.AreEqual(cache["b"], 2, "should get 2");
            Assert.AreEqual(cache["c"], 3, "should get 3");
            Assert.AreEqual(cache["d"], 4, "should get 4");
        }
Пример #9
0
        public static void TestReplace()
        {
            var cache = new LRUCache <string, int>(3);

            cache["a"] = 1;
            cache["b"] = 2;
            cache["c"] = 3;

            int x = default;

            x = cache["a"];
            x = cache["a"];
            x = cache["b"];

            cache["d"] = 4;
            cache["e"] = 5;

            Assert.IsFalse(cache.ContainsKey("a"));
            Assert.AreEqual(cache["b"], 2, "should get 2");
            Assert.IsFalse(cache.ContainsKey("c"));
            Assert.AreEqual(cache["d"], 4, "should get 4");
            Assert.AreEqual(cache["e"], 5, "should get 5");
        }
        private void OnEffectQuery(CurrencyModifierQuery qry)
        {
            // Check the reason is a match
            if (!affectReasons.Contains(qry.reason))
            {
                return;
            }

            // Check if it's non-zero
            float total = 0.0f;

            foreach (Currency currency in currencies)
            {
                total += Math.Abs(qry.GetInput(currency));
            }
            if (total < 0.01f)
            {
                return;
            }

            string hash = string.Join("|", new string[] {
                qry.GetInput(Currency.Funds).ToString("F0"),
                qry.GetInput(Currency.Science).ToString("F0"),
                qry.GetInput(Currency.Reputation).ToString("F0"),
                qry.reason.ToString()
            });

            // Get the multiplier
            float multiplier = 0.0f;

            if (!valueCache.ContainsKey(hash))
            {
                float lowerValue = Parent.GetLeveledListItem(lowerValues);
                float upperValue = Parent.GetLeveledListItem(upperValues);

                multiplier       = (float)(random.NextDouble() * (upperValue - lowerValue) + lowerValue);
                valueCache[hash] = multiplier;
            }
            multiplier = valueCache[hash];

            foreach (Currency currency in currencies)
            {
                float delta = (float)Math.Round(multiplier * qry.GetInput(currency) - qry.GetInput(currency));
                if (delta != 0.0f)
                {
                    qry.AddDelta(currency, delta);
                }
            }
        }
Пример #11
0
        public StatTreNode Filtered(string node, string koder, string bbox)
        {
            node  = node ?? CodeConsts.RootNodeCode;
            koder = koder ?? node;

            string cacheKey    = node + "_" + koder;
            bool   isBboxEmpty = string.IsNullOrWhiteSpace(bbox);

            if (isBboxEmpty && _lruCache.ContainsKey(cacheKey))
            {
                return(_lruCache.Get(cacheKey));
            }

            //var codes = _codeSearch.GetNatureAreaTaxonCodesByCodesAndBbox(koder, bbox);
            var treeNode = _statTreeBuilder.Build(koder, bbox, node);

            var treNode = new StatTreNode
            {
                Kode               = treeNode.Code,
                Navn               = treeNode.Name,
                AntallArter        = treeNode.TaxonCount,
                AntallNaturomrader = treeNode.NatureAreaCount,
                Areal              = treeNode.Area,
                Forelder           = treeNode.Parent != null ? new StatTreNodeForelder {
                    Kode = treeNode.Parent.Code, Navn = treeNode.Parent.Name
                } : null,
                Barn = treeNode.Children.Count > 0
                  ? treeNode.Children.Values.Select(c =>
                                                    new StatTreNodeBarn
                {
                    AntallArter        = c.TaxonCount,
                    AntallNaturomrader = c.NatureAreaCount,
                    Areal   = c.Area,
                    HarBarn = c.HasDescendants,
                    Kode    = c.Code,
                    Navn    = c.Name
                }).ToList()
                  : null
            };

            if (isBboxEmpty)
            {
                _lruCache.Add(cacheKey, treNode);
            }

            return(treNode);
        }
Пример #12
0
 public void FlushMemoizedIDsForTask(string taskName, string argument)
 {
     if (argument == null)
     {
         if (_MemoizationCache.ContainsKey(taskName))
         {
             _MemoizationCache.Remove(taskName);
         }
     }
     else
     {
         LRUCache <string, object> resultCache = null;
         if (_MemoizationCache.TryGetValue(taskName, out resultCache))
         {
             if (resultCache.ContainsKey(argument))
             {
                 resultCache.Remove(argument);
             }
         }
     }
 }
Пример #13
0
        private void OnEffectQuery(CurrencyModifierQuery qry)
        {
            // Check the reason is a match
            if (!affectReasons.Contains(qry.reason))
            {
                return;
            }

            // Check if it's non-zero
            float total = 0.0f;

            foreach (Currency currency in currencies)
            {
                total += Math.Abs(qry.GetInput(currency));
            }
            if (total < 0.01f)
            {
                return;
            }

            float funds   = qry.GetInput(Currency.Funds);
            float science = qry.GetInput(Currency.Science);
            float rep     = qry.GetInput(Currency.Reputation);

            string hash = string.Join("|", new string[] {
                funds.ToString(),
                science.ToString(),
                rep.ToString(),
                qry.reason.ToString()
            });

            // Check whether the contract matches the multiplier
            if (!contractCache.ContainsKey(hash))
            {
                bool     foundMatch = false;
                Contract match      = null;
                foreach (Contract contract in ContractSystem.Instance.Contracts.
                         Where(c => c.ContractState != Contract.State.Completed || c.DateFinished == Planetarium.fetch.time || c.DateFinished == 0.0))
                {
                    // If the contract type doesn't match, don't bother
                    if (!ContractTypeMatches(contract))
                    {
                        continue;
                    }

                    string hash2 = string.Join("|", new string[] {
                        contract.FundsCompletion.ToString(),
                        contract.ScienceCompletion.ToString(),
                        contract.ReputationCompletion.ToString(),
                        TransactionReasons.ContractReward.ToString()
                    });
                    // Check contract values - allow zero values because on reward funds/science/rep all come in seperately
                    if (qry.reason == TransactionReasons.ContractAdvance &&
                        contract.FundsAdvance == funds && science == 0.0 && rep == 0.0 ||
                        qry.reason == TransactionReasons.ContractPenalty &&
                        contract.FundsFailure == funds && science == 0.0 && contract.ReputationFailure == rep ||
                        qry.reason == TransactionReasons.ContractReward &&
                        (contract.FundsCompletion == funds || funds == 0) && (contract.ScienceCompletion == science || (int)science == 0) && (contract.ReputationCompletion == rep || (int)rep == 0))
                    {
                        foundMatch = true;
                        match      = contract;
                        break;
                    }

                    // Check parameter values
                    foreach (ContractParameter parameter in contract.AllParameters)
                    {
                        if (qry.reason == TransactionReasons.ContractPenalty &&
                            parameter.FundsFailure == funds && science == 0.0 && parameter.ReputationFailure == rep ||
                            qry.reason == TransactionReasons.ContractReward &&
                            (parameter.FundsCompletion == funds || funds == 0.0) && (parameter.ScienceCompletion == science || science == 0.0) && (parameter.ReputationCompletion == rep || rep == 0.0))
                        {
                            foundMatch = true;
                            match      = contract;
                            break;
                        }
                    }
                }

                contractCache[hash] = new KeyValuePair <bool, Contract>(foundMatch, match);
            }
            if (!contractCache[hash].Key)
            {
                return;
            }

            // Figure out the vessel to look at
            Vessel vessel = null;

            if (FlightGlobals.ActiveVessel != null)
            {
                vessel = FlightGlobals.ActiveVessel;
            }
            else if (cachedVessel != null && cacheTime < Time.fixedTime + 5.0f)
            {
                vessel = cachedVessel;
            }

            // Check for matching crew
            if (vessel != null && trait != null)
            {
                bool crewFound = false;
                foreach (ProtoCrewMember pcm in VesselUtil.GetVesselCrew(vessel))
                {
                    if (pcm.experienceTrait.Config.Name == trait)
                    {
                        crewFound = true;
                        break;
                    }
                }
                if (!crewFound)
                {
                    return;
                }
            }

            float multiplier = Parent.GetLeveledListItem(multipliers);

            foreach (Currency currency in currencies)
            {
                qry.AddDelta(currency, multiplier * qry.GetInput(currency) - qry.GetInput(currency));
            }
        }
Пример #14
0
        public void TestLRUCache()
        {
            var cache = new LRUCache<string, int>(3); // make a tiny cache of three elements

            Assert.IsTrue(cache.Capacity == 3 && cache.Count == 0);

            // add three elements

            Assert.IsFalse(cache.ContainsKey("one"));
            Assert.IsTrue(cache.Get("one") == 0);
            cache.Add("one", 1);
            Assert.IsTrue(cache.ContainsKeyAt("one", 0));
            Assert.IsTrue(cache.Get("one") == 1);
            Assert.IsTrue(cache.Count == 1);

            Assert.IsFalse(cache.ContainsKey("two"));
            Assert.IsTrue(cache.Get("two") == 0);
            cache.Add("two", 2);
            Assert.IsTrue(cache.ContainsKeyAt("two", 1));
            Assert.IsTrue(cache.Get("two") == 2);
            Assert.IsTrue(cache.Count == 2);

            Assert.IsFalse(cache.ContainsKey("three"));
            Assert.IsTrue(cache.Get("three") == 0);
            cache.Add("three", 3);
            Assert.IsTrue(cache.ContainsKeyAt("three", 2));
            Assert.IsTrue(cache.Get("three") == 3);
            Assert.IsTrue(cache.Count == 3);

            // we're at capacity. if we add another element,
            // "one" will get evicted since it's least recently used

            Assert.IsTrue(cache.Count == cache.Capacity);

            cache.Add("four", 4);
            Assert.IsTrue(cache.Get("four") == 4);

            Assert.IsTrue(cache.Count == 3);
            Assert.IsTrue(cache.ContainsKeyAt("four", 2));  // from the youngest
            Assert.IsTrue(cache.ContainsKeyAt("three", 1)); // ...
            Assert.IsTrue(cache.ContainsKeyAt("two", 0));   // to the oldest
            Assert.IsFalse(cache.ContainsKey("one"));

            // now let's touch "two" because that's the least recently used one.
            // by doing that, we demote "three" to be the least recently used one,
            // and adding a new entry will then evict it.

            Assert.IsTrue(cache.Get("two") == 2); // reading the key will touch it
            Assert.IsTrue(cache.ContainsKeyAt("two", 2));   // now two is the youngest
            Assert.IsTrue(cache.ContainsKeyAt("four", 1));  // ...
            Assert.IsTrue(cache.ContainsKeyAt("three", 0)); // and three is the oldest

            Assert.IsTrue(cache.Count == cache.Capacity);

            cache.Add("five", 5);
            Assert.IsTrue(cache.Get("five") == 5);

            Assert.IsTrue(cache.Count == 3);
            Assert.IsTrue(cache.ContainsKeyAt("five", 2)); // youngest
            Assert.IsTrue(cache.ContainsKeyAt("two", 1));  // ...
            Assert.IsTrue(cache.ContainsKeyAt("four", 0)); // oldest
            Assert.IsFalse(cache.ContainsKey("three")); // evicted as lru

            // finally we remove one item, dropping the count.
            // adding another item will not cause evictions

            Assert.IsTrue(cache.Remove("four"));
            Assert.IsFalse(cache.ContainsKey("four"));
            Assert.IsTrue(cache.Get("four") == 0);

            Assert.IsTrue(cache.Count == cache.Capacity - 1);

            cache.Add("six", 6);
            Assert.IsTrue(cache.Get("six") == 6);

            Assert.IsTrue(cache.Count == 3);
            Assert.IsTrue(cache.ContainsKeyAt("six", 2));  // youngest
            Assert.IsTrue(cache.ContainsKeyAt("five", 1)); // ...
            Assert.IsTrue(cache.ContainsKeyAt("two", 0));  // oldest
            Assert.IsFalse(cache.ContainsKey("four"));   // removed manually

            // test clearing

            cache.Clear();
            Assert.IsTrue(cache.Count == 0);
        }
Пример #15
0
        public void LRUCache_MaxItems()
        {
            LRUCache <int, int> cache;
            int value;

            cache = new LRUCache <int, int>();
            Assert.AreEqual(0, cache.Count);
            Assert.AreEqual(int.MaxValue, cache.MaxItems);
            cache.MaxItems = 3;

            //---------------------------------------------

            cache.Clear();
            for (int i = 0; i < 3; i++)
            {
                cache.Add(i, i);
            }

            Assert.AreEqual(3, cache.Count);
            cache.Add(3, 3);
            Assert.AreEqual(3, cache.Count);

            Assert.IsFalse(cache.ContainsKey(0));
            Assert.IsTrue(cache.ContainsKey(1));
            Assert.IsTrue(cache.ContainsKey(2));
            Assert.IsTrue(cache.ContainsKey(3));

            //---------------------------------------------

            cache.Clear();
            for (int i = 0; i < 3; i++)
            {
                cache[i] = i;
            }

            Assert.AreEqual(3, cache.Count);
            cache[3] = 3;
            Assert.AreEqual(3, cache.Count);

            Assert.IsFalse(cache.ContainsKey(0));
            Assert.IsTrue(cache.ContainsKey(1));
            Assert.IsTrue(cache.ContainsKey(2));
            Assert.IsTrue(cache.ContainsKey(3));

            //---------------------------------------------

            cache.Clear();
            for (int i = 0; i < 3; i++)
            {
                cache[i] = i;
            }

            Assert.AreEqual(3, cache.Count);
            cache.MaxItems = 2;
            Assert.AreEqual(2, cache.Count);

            Assert.IsFalse(cache.ContainsKey(0));
            Assert.IsTrue(cache.ContainsKey(1));
            Assert.IsTrue(cache.ContainsKey(2));

            cache.MaxItems = 3;

            //---------------------------------------------

            cache.Clear();
            for (int i = 0; i < 3; i++)
            {
                cache[i] = i;
            }

            Assert.IsTrue(cache.ContainsKey(0));

            Assert.AreEqual(3, cache.Count);
            cache[3] = 3;
            Assert.AreEqual(3, cache.Count);

            Assert.IsTrue(cache.ContainsKey(0));
            Assert.IsFalse(cache.ContainsKey(1));
            Assert.IsTrue(cache.ContainsKey(2));
            Assert.IsTrue(cache.ContainsKey(3));

            //---------------------------------------------

            cache.Clear();
            for (int i = 0; i < 3; i++)
            {
                cache[i] = i;
            }

            cache.Touch(0);

            Assert.AreEqual(3, cache.Count);
            cache[3] = 3;
            Assert.AreEqual(3, cache.Count);

            Assert.IsTrue(cache.ContainsKey(0));
            Assert.IsFalse(cache.ContainsKey(1));
            Assert.IsTrue(cache.ContainsKey(2));
            Assert.IsTrue(cache.ContainsKey(3));

            //---------------------------------------------

            cache.Clear();
            for (int i = 0; i < 3; i++)
            {
                cache[i] = i;
            }

            cache.TryGetValue(0, out value);

            Assert.AreEqual(3, cache.Count);
            cache[3] = 3;
            Assert.AreEqual(3, cache.Count);

            Assert.IsTrue(cache.ContainsKey(0));
            Assert.IsFalse(cache.ContainsKey(1));
            Assert.IsTrue(cache.ContainsKey(2));
            Assert.IsTrue(cache.ContainsKey(3));

            //---------------------------------------------

            cache.Clear();
            for (int i = 0; i < 6; i++)
            {
                cache[i] = i;
            }

            cache.TryGetValue(0, out value);

            Assert.AreEqual(3, cache.Count);
            cache[3] = 3;
            Assert.AreEqual(3, cache.Count);

            Assert.IsFalse(cache.ContainsKey(0));
            Assert.IsFalse(cache.ContainsKey(1));
            Assert.IsFalse(cache.ContainsKey(2));
            Assert.IsTrue(cache.ContainsKey(3));
            Assert.IsTrue(cache.ContainsKey(4));
            Assert.IsTrue(cache.ContainsKey(5));
        }
Пример #16
0
        private void Redraw()
        {
            if (mapProvider == null)
            {
                return;
            }
            if (position == null)
            {
                return;
            }
            if (zoomFactor == 0)
            {
                return;
            }

            var basePoint = Projection.GeoPointToMappoint(position, zoomFactor);
            var baseTile  = Projection.MappointToTile(basePoint);

            var toRemove = TilesHolder.Children.OfType <UIElement>().Where(item => { return
                                                                                     ((Canvas.GetLeft(item) + baseTile.TileSize < 0) ||
                                                                                      (Canvas.GetTop(item) + baseTile.TileSize < 0) ||
                                                                                      (Canvas.GetLeft(item) > this.RenderSize.Width) ||
                                                                                      (Canvas.GetTop(item) > this.RenderSize.Height)); }).ToArray();

            foreach (UIElement item in toRemove)
            {
                TilesHolder.Children.Remove(item);
            }


            Point center = new Point(this.RenderSize.Width / 2, this.RenderSize.Height / 2);

            int tilesInWidth  = ((int)this.RenderSize.Width / Projection.TileSize) + 2;
            int tilesInHeight = ((int)this.RenderSize.Height / Projection.TileSize) + 2;

            MapPoint upperLeftPoint = new MapPoint(basePoint.X - center.X, basePoint.Y - center.Y, basePoint.ZoomFactor, basePoint.TileSize);
            Tile     upperLeftTile  = Projection.MappointToTile(upperLeftPoint);

            double startX = upperLeftTile.MapPoint1.X - upperLeftPoint.X;
            double startY = upperLeftTile.MapPoint1.Y - upperLeftPoint.Y;

            for (int x = 0; x < tilesInWidth; x++)
            {
                for (int y = 0; y < tilesInHeight; y++)
                {
                    Tile    tile = new Tile(x + upperLeftTile.TileX, y + upperLeftTile.TileY, upperLeftTile.ZoomFactor, upperLeftTile.TileSize);
                    MapTile mapTile;
                    if (!cache.TryGetValue(tile, out mapTile))
                    {
                        mapTile = new MapTile(this.Projection, tile);

                        actions.Enqueue(() => {
                            if (cache.ContainsKey(tile))
                            {
                                return;
                            }
                            Brush tileBitmap = mapProvider.GetTile(tile);
                            cache.Add(tile, mapTile);
                            mapTile.Brush = tileBitmap;
                        });
                    }
                    Canvas.SetLeft(mapTile, startX + upperLeftTile.TileSize * x);
                    Canvas.SetTop(mapTile, startY + upperLeftTile.TileSize * y);
                    if (TilesHolder.Children.Contains(mapTile))
                    {
                        continue;
                    }
                    TilesHolder.Children.Add(mapTile);
                }
            }
        }