3

I'm using .net 4.7.2 (not core) and C#.

I need to come up with a way to to not block my current async tasks and I have a need to search for a user as part of these tasks. I've done DirectorySearcher operations previously so I know the attachment to AD and first search can take a few seconds which will really throw a wrench in the gears if I try calling it from my existing async methods.

I found that the DirectorySearcher has an "Asynchronous" property. But I don't think it does the async pattern.

        DirectorySearcher ds = new DirectorySearcher();
        ds.Asynchronous = true;
        ds.Filter = "(&(objectclass=user)(samaccountname=testaccount)";
        ds.PropertiesToLoad.Add("samaccountname");
        SearchResult sr = await ds.FindOne();

Of course, the last line throws an error because FindOne is not an async method. I already know that if I remove the await it will compile. But that doesn't solve my problem with calling this from existing awaited methods. I need to find a way to do an async search in AD...

Does anyone know how I could get this to work in the .net framework (not core)?

VillageTech
  • 1,968
  • 8
  • 18
Zonus
  • 2,313
  • 2
  • 26
  • 48
  • Remove `await`? https://learn.microsoft.com/en-us/dotnet/api/system.directoryservices.directorysearcher?view=netframework-4.7.2 – Samvel Petrosov Jan 15 '20 at 23:24
  • Asynchronous is not what you think it is, in terms of DirectorySearcher. It finds a record and returns it while it continues to search for more. [Read here](https://learn.microsoft.com/en-us/dotnet/api/system.directoryservices.directorysearcher.asynchronous?view=netframework-4.7.2#System_DirectoryServices_DirectorySearcher_Asynchronous) – Jawad Jan 15 '20 at 23:28
  • I know removing the "await" will "fix" the above code. However, it will a blocking set of code when called from my other await methods. – Zonus Jan 15 '20 at 23:31
  • Here is another thread which uses task.run with principalContext instead of directorySearcher. [See here](https://stackoverflow.com/a/38925562/1390548) – Jawad Jan 15 '20 at 23:49
  • [Related](https://stackoverflow.com/a/13505076/2791540) – John Wu Jan 16 '20 at 22:31

2 Answers2

1

Try running it on the thread pool.

private async void MyAsyncMethod()
{
   // do some asynchronous thing
   // await something

   // then, run below on thread pool, which would not block MyAsyncMethod
   Task.Run(() =>
   {
      DirectorySearcher ds = new DirectorySearcher();
      ds.Asynchronous = true;
      ds.Filter = "(&(objectclass=user)(samaccountname=testaccount)";
      ds.PropertiesToLoad.Add("samaccountnamt");
      SearchResult sr = ds.FindOne();
   });
}

For reference: https://learn.microsoft.com/dotnet/api/system.threading.tasks.task.run

kurakura88
  • 2,185
  • 2
  • 12
  • 18
  • 1
    My only concern is that this still can be a blocking method. https://learn.microsoft.com/en-us/dotnet/standard/threading/the-managed-thread-pool Under "When not to use thread pool threads" - "You have tasks that cause the thread to block for long periods of time. The thread pool has a maximum number of threads, so a large number of blocked thread pool threads might prevent tasks from starting." – Zonus Jan 16 '20 at 00:54
1

None of MS products do this....

I did find an active nuget project called ldap4net which does.

Zonus
  • 2,313
  • 2
  • 26
  • 48