I am not aware of async AFSearch methods so encapsulating them in an async Task as you have done is one way to get around this.
I prefer to avoid the usage of AFSearchTokens and use a query string instead.
AFElementSearch search = new AFElementSearch(_piAFDatabase, "NameofMySearch", @"Template:=templateName AllDescendants:=true");
return new List<Guid>(search.FindObjectIds())
- AllDescendants: If not specified, this filter is enabled by default.
- When the elements are returned from a find operation, they are only partially loaded into memory, typically enough to display their inherent properties, such as Name, Description, Template, Type, etc. When a piece of information is accessed in the element that requires more information, an RPC to the server is made to fully load the element. By having the search return the object IDs, then the LoadElements can be called to load all information in bulk and reduce the number of RPCs made to retrieve this information.
AFNamedCollection<AFElement> elements = AFElement.LoadElements(_piAFDatabase, returnValue, null);