简体   繁体   中英

Make Method wait for result from Async Call

I have a limited understanding of aysnc so apologies if this is basic.

I'm using the Lync SDK to query contacts in my method, the SDK uses async to perform the search and returns the results fine to my call back.

I'd like to have my method SearchForContact not return to its caller under all the results have been obtained but I have no idea how to do this.

Thanks.

 public void SearchForContact(string search)
    {
        var searchFields = _LyncClient.ContactManager.GetSearchFields();

        object[] _asyncState = { _LyncClient.ContactManager, search };

        _LyncClient.ContactManager.BeginSearch(search, SearchProviders.GlobalAddressList | SearchProviders.ExchangeService
            , searchFields
            , SearchOptions.Default
            , 10
            , result =>
            {
                searchForContactResults = new List<MeetingContact>();

                SearchResults results = null;
                results = ((ContactManager)_asyncState[0]).EndSearch(result);
                if(results == null)
                    return;

                MeetingContact contactResult = new MeetingContact();

                foreach (var searchResult in results.AllResults)
                {
                    var c = searchResult.Result as Contact;

                    contactResult.FullName = c.GetContactInformation(ContactInformationType.DisplayName).ToString();
                    contactResult.SipAddress = c.Uri;  

                    searchForContactResults.Add(contactResult);

                }

                if (ResultOfSearchForContactEvent != null) ResultOfSearchForContactEvent(searchForContactResults); //returns results to subscriber fine, however I'd perfer not to do this
            }
            , _asyncState);

        //I want to return List<MeetingContact> here once BeginSearch has completed 

    }

EDIT:

so I've essentially done it by making the thread sleep until BeginSearch is complete. There must be a better way?

public List<MeetingContact> SearchForContact(string search)
        {
            var searchFields = _LyncClient.ContactManager.GetSearchFields();

            object[] _asyncState = { _LyncClient.ContactManager, search };

            bool isComplete = false;

            _LyncClient.ContactManager.BeginSearch(search, SearchProviders.GlobalAddressList | SearchProviders.ExchangeService
                , searchFields
                , SearchOptions.Default
                , 10
                , result =>
                {
                    searchForContactResults = new List<MeetingContact>();

                    SearchResults results = null;
                    results = ((ContactManager)_asyncState[0]).EndSearch(result);
                    if(results == null)
                        return;

                    MeetingContact contactResult = new MeetingContact();

                    foreach (var searchResult in results.AllResults)
                    {
                        var c = searchResult.Result as Contact;

                        contactResult.FullName = c.GetContactInformation(ContactInformationType.DisplayName).ToString();
                        contactResult.SipAddress = c.Uri;  

                        searchForContactResults.Add(contactResult);

                    }

                    isComplete = true;

                }, _asyncState);

            while (isComplete == false)
            {
                Thread.Sleep(50);
            }

            return searchForContactResults;

        }

I would never recommend "blocking". I would recommend using async/await instead. To do this with the above example, convert the async method into a task using Task.Factory.FromAsync and just await on it.

So your example would be:

public async Task<List<MeetingContact>> SearchForContact(string search)
{
    var searchFields = _LyncClient.ContactManager.GetSearchFields();
    var searchResults = await Task<SearchResults>.Factory.FromAsync((ar, o) => _LyncClient.ContactManager.BeginSearch(search, SearchProviders.GlobalAddressList | SearchProviders.ExchangeService, searchFields, SearchOptions.Default, 10, ar, o), _LyncClient.ContactManager.EndSearch, null);
    var searchForContactResults = new List<MeetingContact>();

    if (searchResults == null)
        return searchForContactResults;

    foreach (var searchResult in searchResults.Contacts)
    {
        var contactResult = new MeetingContact
        {
            FullName = searchResult.GetContactInformation(ContactInformationType.DisplayName).ToString(),
            SipAddress = searchResult.Uri
        };

        searchForContactResults.Add(contactResult);

    }

    return searchForContactResults;
}

If you really, really have to block (which I strongly argue against) then all you have to do is drop the async/await and call .Result on the task like so:

public List<MeetingContact> SearchForContact(string search)
{
    var searchFields = _LyncClient.ContactManager.GetSearchFields();
    var searchResults = Task<SearchResults>.Factory.FromAsync((ar, o) => _LyncClient.ContactManager.BeginSearch(search, SearchProviders.GlobalAddressList | SearchProviders.ExchangeService, searchFields, SearchOptions.Default, 10, ar, o), _client.ContactManager.EndSearch, null).Result;
    var searchForContactResults = new List<MeetingContact>();

    if (searchResults == null)
        return searchForContactResults;

    foreach (var searchResult in searchResults.Contacts)
    {
        var contactResult = new MeetingContact
        {
            FullName = searchResult.GetContactInformation(ContactInformationType.DisplayName).ToString(),
            SipAddress = searchResult.Uri
        };

        searchForContactResults.Add(contactResult);

    }

    return searchForContactResults;
}

In order to block until search is completed, try invoking BeginSearch() in following way:

SearchResults results = _LyncClient.ContactManager.EndSearch(_LyncClient.ContactManager.BeginSearch(search, SearchProviders.GlobalAddressList | SearchProviders.ExchangeService, searchFields, SearchOptions.Default, 10, null, _asyncState));

For more info refer to : Asynchronous programming in Lync SDK

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM