Как использовать Task.Factory.FromAsyn c с библиотекой ldap - PullRequest
0 голосов
/ 26 февраля 2020

Я нашел этот класс онлайн:

public class AsyncSearcher
{
    LdapConnection _connect;

    public AsyncSearcher(LdapConnection connection)
    {
        this._connect = connection;
        this._connect.AutoBind = true; //will bind on first search
    }

    public void BeginPagedSearch(
            string baseDN,
            string filter,
            string[] attribs,
            int pageSize,
            Action<SearchResponse> page,
            Action<Exception> completed                
            )
    {
        if (page == null)
            throw new ArgumentNullException("page");

        AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(null);

        Action<Exception> done = e =>
            {
                if (completed != null) asyncOp.Post(delegate
                {
                    completed(e);
                }, null);
            };

        SearchRequest request = new SearchRequest(
            baseDN,
            filter,
            System.DirectoryServices.Protocols.SearchScope.Subtree,
            attribs
            );

        PageResultRequestControl prc = new PageResultRequestControl(pageSize);

        //add the paging control
        request.Controls.Add(prc);

        AsyncCallback rc = null;

        rc = readResult =>
            {
                try
                {
                    var response = (SearchResponse)_connect.EndSendRequest(readResult);
                    
                    //let current thread handle results
                    asyncOp.Post(delegate
                    {
                        page(response);
                    }, null);

                    var cookie = response.Controls
                        .Where(c => c is PageResultResponseControl)
                        .Select(s => ((PageResultResponseControl)s).Cookie)
                        .Single();

                    if (cookie != null && cookie.Length != 0)
                    {
                        prc.Cookie = cookie;
                        _connect.BeginSendRequest(
                            request,
                            PartialResultProcessing.NoPartialResultSupport,
                            rc,
                            null
                            );
                    }
                    else done(null); //signal complete
                }
                catch (Exception ex) { done(ex); }
            };


        //kick off async
        try
        {
            _connect.BeginSendRequest(
                request,
                PartialResultProcessing.NoPartialResultSupport,
                rc,
                null
                );
        }
        catch (Exception ex) { done(ex); }
    }

}

Я в основном пытаюсь преобразовать приведенный ниже код, который пишет в консоль, чтобы вернуть данные из Task.Factory.FromAsync, чтобы я мог использовать данные в другом месте.

using (LdapConnection connection = CreateConnection(servername))
        {
            AsyncSearcher searcher = new AsyncSearcher(connection);

            searcher.BeginPagedSearch(
                baseDN,
                "(sn=Dunn)",
                null,
                100,
                f => //runs per page
                {
                    foreach (var item in f.Entries)
                    {
                        var entry = item as SearchResultEntry;

                        if (entry != null)
                        {
                            Console.WriteLine(entry.DistinguishedName);
                        }
                    }

                },
                c => //runs on error or when done
                {
                    if (c != null) Console.WriteLine(c.ToString());
                    Console.WriteLine("Done");
                    _resetEvent.Set();
                }
            );

            _resetEvent.WaitOne();
            
        }

Я пробовал это, но получаю следующие синтаксические ошибки:

            LdapConnection connection1 = CreateConnection(servername);
            AsyncSearcher1 searcher = new AsyncSearcher1(connection1);


            async Task<SearchResultEntryCollection> RootDSE(LdapConnection connection)
            {
                return await Task.Factory.FromAsync(,

                        () =>
                            {
                                return searcher.BeginPagedSearch(baseDN, "(cn=a*)", null, 100, f => { return f.Entries; }, c => { _resetEvent.Set(); });
                            }
                        );
            }

            _resetEvent.WaitOne();

1 Ответ

1 голос
/ 28 февраля 2020

Стиль асинхронного кода APM («Модель асинхронного программирования») использует пары методов Begin и End вместе с IAsyncResult, следуя заданному шаблону c .

Метод Task.Factory.FromAsync предназначен для объединения пар методов APM в современный стиль асинхронного кода TAP («асинхронное программирование на основе задач») .

Однако FromAsync * Для 1014 * требуется , чтобы методы следовали шаблону APM точно , а BeginPagedSearch не следует шаблону APM. Так что вам нужно будет использовать TaskCompletionSource<T> напрямую. TaskCompletionSource<T> может использоваться для преобразования любого существующего асинхронного шаблона в TAP , если он имеет единственный результат.

Метод, который вы пытаетесь обернуть, имеет несколько обратных вызовов, поэтому он не может быть сопоставлен с TAP вообще. Если вы хотите собрать все наборов результатов и вернуть их список, тогда вы можете использовать TaskCompletionSource<T> для этого. В противном случае вы захотите использовать что-то вроде IAsyncEnumerable<T>, что потребует написания вашей собственной реализации BeginPagedSearch.

...