ThinkGeo.com    |     Documentation    |     Premium Support

WmsRasterLayer version 13.2

Hello,

I try to upgrade my apps to Version 13.2 from 13.0 with the new Async Methods and use now WmsRasterLayer from the Async-Namespace.

There are some more changes in code necessary as mentioned in the blog post “ThinkGeo UI 13.2 is Released”, for example OpenAsync and CloseAsync.

Now it seems important where in the constructor the CRS-Parameter for the layer is set. Depending on this, the BoundingBoxCore method returns correct results for the crs or not.

The following lines from a log-file shows, that GetBoundingBoxCore returns wrong BBox for the Crs.

set_InternalEpsgCode InternalEpsgCode CRS: EPSG:25833
GetBoundingBoxCore CRS: EPSG:25833
BBox: -85.0511287798066,180,85.0511287798066,-180

My code in the constructor is something like that:

public class TisWMSRasterLayerModel : ThinkGeo.Core.Async.WmsRasterLayer
…
public TisWMSRasterLayerModel(IWebProxy _webProxy) : base()
{
...
this.UpperThreshold = double.MaxValue;
this.LowerThreshold = 0;
this.IsTransparent = true;
this.TimeoutInSecond = 30;

// if uncommented the following line, it works as expected
// this.Crs = $"EPSG:{25832}";

….
var allLayers = this.GetServerLayers();
Collection<string> styles = this.GetServerStyleNames();
Collection<string> exFormats = this.GetServerExceptionFormats();
this.ServerCapabilitiesAsString = this.GetServerCapabilitiesXml();
if (haveToClose) await this.CloseAsync();
….
this.Crs = $"EPSG:{internalEpsgCode.ToString()}";

}

Please give me some hints

Regards Torsten

Hi Torsten,

The Crs property is applied in OpenAsync(), I see CloseAsync() in your code, so I supposed you called OpenAsync() somewhere before that, right? Please make sure Crs is correctly set before OpenAsync().

Also please don’t call OpenAsync in the constructor of the sub class, OpenAsync() will be called properly when this layer being rendered. The recommended way of customization is to create a Customized WmsRasterSource, and use it in the CustomizedWmsRasterLayer, something like following:

class CustomizedWmsRasterSource : ThinkGeo.Core.Async.WmsRasterSource
{
    protected override Task OpenAsyncCore()
    {
        // Make sure the CRS is correctly set before calling base.OpenAsyncCore
        return base.OpenAsyncCore();
    }
}

class CustomizedWmsRasterLayer : ThinkGeo.Core.Async.WmsRasterLayer
{
    CustomizedWmsRasterLayer()
    {
        ImageSource = new CustomizedWmsRasterSource();
    }
}

The idea is the concept of RasterSource is for the dataset while layer is for rendering, so most of your customized code should be in the RasterSource instead of RasterLayer.

Also, you can see the CRS is set in OpenAsyncCore in the demo code. Please don’t put too much code in the constructor, as constructor is supposed to be fast and never throwing exceptions, put the initialization code in OpenAsyncCore instead.

Let me know if you have more questions.

Thanks,
Ben

Hi Ben,

Thank you for the fast response. Your Suggestion was very helpful.

Thanks,
Torsten

Awesome! Just let us know for any questions.

Hi Ben,
some more Questions:

  • It is recommanded to use await RefeshAsync? The HowDo-Examples don’t use it?

  • It’s possible to cancel OpenAsync? Sometimes the app hang’s, on OpenAnsyc sometimes not by the same url.

    async static Task<Tuple<bool, string>> staticTryOpenAsync(string uriString, IWebProxy webProxy)
    {
    string error = string.Empty;
    bool result = false;
    var uri = new Uri(uriString);
    ThinkGeo.Core.Async.WmsRasterLayer wmsRasterLayer = new ThinkGeo.Core.Async.WmsRasterLayer(uri, webProxy);
    try
    {
    // sometimes there is no return from OpenAsync
    await wmsRasterLayer.OpenAsync();
    var layers = wmsRasterLayer.GetServerLayers();
    await wmsRasterLayer.CloseAsync();
    result = true;
    }
    catch (Exception x)
    {
    error = x.ToString();
    result = false;
    logger.Error(x);
    }
    return new Tuple<bool, string>(result, error);
    }

Regards
Torsten

Hi Torsten,

All the HowDoI samples should have been updated and use Async version of APIs when we released v13.2 (on both develop and master brach). Please pull the latest and if you still see Non-Async APIs in the samples. let us know which sample it is.

WmsRasterLayer has TimeOutInSeconds property, a web request (OpenAsync() or DrawAsync() method) will be canceled and throwing a TaskCanceledException when the time is out. Is this working for you. I’m thinking it might be better to add an overload OpenAsync(CancellationToken), I’ve logged that down.

We recently fixed some issues in WMS so please make sure get the latest version: ThinkGeo.Core 13.3.0-beta005 uploaded successful.

Thanks,
Ben

Hi Ben,
Thank you for your Response. I have installed the beta-Version from ThinkGeo.Core. But the problem with OpenAsync is still present.
I can’t reproduce the behavior in a small sample project. I store some params for the layer in a database. When I load the params in a loop and create the appropriate layers; the app hangs by OpenAsnc, when the app creates the second WMS layer and for both IsVisbile is true.
PseudoCode:

Task<bool> canCreateLayerFromParams(StoredLayer slayer)
{
   try
   {
   switch(slayer.TheType)
   {
      …
      case (WmsLayer): 
      {
           WmsRasteSource sc = new WmsRasteSource(sLayer.Uri);
           // hang by the second wmsrasterLayer, if the Overlay.IsVisible = true for the first wmslayer 
           await sc.TryOpen();
           sc.GetServerLayers();
           await sc.CloseAsny();
           return true;
     )
}
catch() 
{
   return false;
}

async createLayers()
{
   foreach (var storedLayer in storedLayersToLoad) 
   {
      var canCreate = Task.Run(() => canCreateLayerFromParams(storedLayer).Result;
      if (canCreate == false) continue; 
      var thinkgeoLayer = createLayerFromParams(storedLayer); 
      LayerOverlay ovl = new(LayerOverlay);
      ovl.Layers.Add(thinkgeoLayer);
      ovl.IsVisible = storedLayer.IsVisible;
      thinkGeoMapControl.Overlays.Add(ovl);
  }
 await thinkGeoMapControl.RefreshAsync();
}

Regards
Torsten

Hi Torsten,

Here are a couple things you can check out.

  1. please don’t use Task.Result, it could bring in deadlock in some scenario. Can you just use
    var canCreate = await canCreateLayerFromParams(storedLayer) as it’s within an async method(async createLayers)?

  2. I don’t think it has anything to do with the Overlay, change your createLayers to following see if you can recreate the issue:

    async createLayers()
    {
    foreach (var storedLayer in storedLayersToLoad)
    {
    //var canCreate = Task.Run(() => canCreateLayerFromParams(storedLayer).Result;
    var canCreate = await canCreateLayerFromParams(storedLayer);
    if (canCreate == false) continue;
    var thinkgeoLayer = createLayerFromParams(storedLayer);
    / /LayerOverlay ovl = new(LayerOverlay);
    // ovl.Layers.Add(thinkgeoLayer);
    // ovl.IsVisible = storedLayer.IsVisible;
    // thinkGeoMapControl.Overlays.Add(ovl);
    }
    await thinkGeoMapControl.RefreshAsync();
    }

  3. let’s confirm if it’s layer specific or it has something to do with the order. Can you add the 2nd layer first and then add the 1st layer, see if it has the same issue?

  4. Now what happened if you set layer.TimeOutInSecond? does it throw an exception when the time out? or it just hand up there never throwing an exception?

Also please let me know the version number of your core, and if you still have the issue, you can send us the WMS server uri and we can test it on our side.

Thanks,
Ben

Hi Ben,

The Problem is solved by using await instead Task.Result. Thanks for your suggestion.
When I use Task.Result the setting of TimeOutInSeconds have no effect. Also, the order of the wmslayers is no important.

Thanks,
Torsten

That’s great, Torsten!