QueuedTask.Run(...).Wait() hangs and await QueuedTask.Run(...) makes QueuedTask busy for too long

518
3
01-31-2024 03:10 AM
Shahadat_1200
New Contributor

QueuedTask.Run(..) hangs when I use Wait() method

 

 public void SetFeatureLayerSymbolAsync(ArcGIS.Desktop.Mapping.FeatureLayer ftrLayer, CIMSymbol symbolToApply)
 {
     if (ftrLayer == null || symbolToApply == null)
         throw new System.ArgumentNullException();
     CIMSimpleRenderer currentRenderer = QueuedTask.Run(()=> ftrLayer.GetRenderer() as CIMSimpleRenderer).Result;
     if (currentRenderer == null)
         return;
     symbolToApply.SetRealWorldUnits(ftrLayer.UsesRealWorldSymbolSizes);
     currentRenderer.Symbol = symbolToApply.MakeSymbolReference();
     QueuedTask.Run(()=> ftrLayer.SetRenderer(currentRenderer)).Wait();
 }

 

And If I use await, it doesn't go to the next line(line 18), returns to the caller method(line 3) and QueuedTask still remains busy(line 4)

 

 public void SetCustomPictureSymbol(ArcGIS.Desktop.Mapping.FeatureLayer featureLayer)
 {
     SetFeatureLayerSymbolAsync(featureLayer, _symbol.Symbol);
     if (QueuedTask.Busy)
         Task.Delay(1000);
 }

 public async Task SetFeatureLayerSymbolAsync(ArcGIS.Desktop.Mapping.FeatureLayer ftrLayer, CIMSymbol symbolToApply)
 {
     if (ftrLayer == null || symbolToApply == null)
         throw new System.ArgumentNullException();
     CIMSimpleRenderer currentRenderer = QueuedTask.Run(()=> ftrLayer.GetRenderer() as CIMSimpleRenderer).Result;
     if (currentRenderer == null)
         return;
     symbolToApply.SetRealWorldUnits(ftrLayer.UsesRealWorldSymbolSizes);
     currentRenderer.Symbol = symbolToApply.MakeSymbolReference();
     await QueuedTask.Run(()=> ftrLayer.SetRenderer(currentRenderer));
     if (QueuedTask.Busy)
     {
         Task.Delay(1000);
     }
 }

 

 

 

0 Kudos
3 Replies
KenBuja
MVP Esteemed Contributor

Why are you applying the Wait method? Your code is almost the same as in the documentation, but it wraps everything in the QueuedTask and doesn't include the Wait method.

public Task SetFeatureLayerSymbolAsync(FeatureLayer ftrLayer, CIMSymbol symbolToApply)
{
  if (ftrLayer == null || symbolToApply == null)
    throw new System.ArgumentNullException();

  return QueuedTask.Run(() =>
  {

    //Get simple renderer from the feature layer
    CIMSimpleRenderer currentRenderer = ftrLayer.GetRenderer() as CIMSimpleRenderer;
    if (currentRenderer == null)
      return;

    //Set symbol's real world setting to be the same as that of the feature layer
    symbolToApply.SetRealWorldUnits(ftrLayer.UsesRealWorldSymbolSizes);

    //Update the symbol of the current simple renderer
    currentRenderer.Symbol = symbolToApply.MakeSymbolReference();
    //Update the feature layer renderer
    ftrLayer.SetRenderer(currentRenderer);
  });
}

 

0 Kudos
Shahadat_1200
New Contributor

Thank you for your Reply @KenBuja  !

We want to do it for multiple layers. For single layer it works this way but for multiple it doesn't. For the second layer it gets QueuedTask busy when we try to Run it. To fix this we were trying Wait, await and other ways.

It fails in all cases. 

0 Kudos
StephenRhea_NV5
Occasional Contributor

Instead of using smaller QueuedTask calls everywhere, I've found that it's better to wrap the calls in a QueuedTask so everything executes in the same task. That would also allow you to remove the Async from SetFeatureLayerSymbol Something like:

public async Task ApplySymbologyAsync()
{
  IEnumerable<FeatureLayer> featureLayers = ActiveMap.GetLayersAsFlattenedList().OfType<FeatureLayer>();
  await QueuedTask.Run(() =>
  {
    foreach (FeatureLayer featureLayer in featureLayers)
    {
      SetFeatureLayerSymbol(featureLayer, {howeverYouObtainYourSymbol});
    }
  });
}

public void SetFeatureLayerSymbolAsync(ArcGIS.Desktop.Mapping.FeatureLayer ftrLayer, CIMSymbol symbolToApply)
{
  if (ftrLayer == null || symbolToApply == null)
    throw new System.ArgumentNullException();
  CIMSimpleRenderer currentRenderer = ftrLayer.GetRenderer() as CIMSimpleRenderer;
  if (currentRenderer == null)
    return;
  symbolToApply.SetRealWorldUnits(ftrLayer.UsesRealWorldSymbolSizes);
  currentRenderer.Symbol = symbolToApply.MakeSymbolReference();
  ftrLayer.SetRenderer(currentRenderer);
 }

 

0 Kudos