2016-09-20 2 views
0

Я новичок в C# & Я пытаюсь использовать Lync SDK для поиска пользователя Lync программно, чтобы получить свой статус. Я не уверен, как передать результаты в ответ на webservice, когда выполняется обратный вызов async.C# как захватить результаты async?

Это код:

Webservice контроллер GET конечная точка:

 // GET: api/Lync/5 
      public String Get(int id) 
    { 
     log.Info("[GET] Search for Lync User: " + id); 

     Lync lync = new Lync(); 

     ////lync.signIn(); 
     Boolean isSignedIn = lync.isUserSignedIn(); 

     if (isSignedIn) 
     { 
      log.Info("User is Signed In"); 
      Console.Write("Enter search key : "); 
      lync.Search("medina"); 

      //lync.Search("medina", 
      //(lyncContacts) => 
      //{ 
      // log.Debug("Search Results Callback fired!"); 
      // log.Info("Results found: " + lyncContacts.Count); 
      // return lyncContacts.ToString(); 
      //}); 
      //Console.WriteLine(name); 
      //Console.ReadLine(); 
      return "testUser"; 
     } 
     else 
     { 
      log.Info("User is not Signed In!"); 
      // TODO: Return status 500 
      return "testUser"; 
     } 
     //Console.ReadLine(); 
     //return "testUser"; 
    } 

выше метод вызывает бизнес-сервис lync.search (..), который выглядит следующим образом:

 public void Search(string searchKey) 
    { 
     List<LyncContact> contactList = new List<LyncContact>(); 
     //List<ContactInformationType> ContactInformationList = new List<ContactInformationType>(); 
     //ContactInformationList.Add(ContactInformationType.Activity); 
     //ContactInformationList.Add(ContactInformationType.Availability); 
     // ContactInformationList.Add(ContactInformationType.CapabilityString); 

     //ContactSubscription contactSubscription = LyncClient.GetClient().ContactManager.CreateSubscription(); 

     Console.WriteLine("Searching for contacts on " + searchKey); 

     LyncClient.GetClient().ContactManager.BeginSearch(
      searchKey, 
      (ar) => 
      { 
       SearchResults searchResults = LyncClient.GetClient().ContactManager.EndSearch(ar); 
       if (searchResults.Contacts.Count > 0) 
       { 
        log.Info("Search results found: " + searchResults.Contacts.Count); 

        Console.WriteLine(searchResults.Contacts.Count.ToString() + " found"); 

        foreach (Contact contact in searchResults.Contacts) 
        { 
         String displayName = contact.GetContactInformation(ContactInformationType.DisplayName).ToString(); 
         ContactAvailability currentAvailability = (ContactAvailability)contact.GetContactInformation(ContactInformationType.Availability); 

         Console.WriteLine(
           contact.GetContactInformation(ContactInformationType.DisplayName).ToString() + " " + contact.GetContactInformation(ContactInformationType.Availability).ToString()); 

         log.Debug("Display Name: " + displayName); 
         log.Debug("Availability: " + currentAvailability); 
         LyncContact lyncContact = new LyncContact.Builder().DisplayName("Snehil").Availability("Busy").build(); 

         contactList.Add(lyncContact); 
         //done(contactList); 
        } 
        return; 
       } 
       else 
       { 
        log.Info("No Results found!"); 
        //done(contactList); 
        return; 
       } 
      }, 
      null); 
    }  else 
       { 
        log.Info("No Results found!"); 
        //done(contactList); 
        return; 
       } 
      }, 
      null); 
    } 

Я попытался использовать Task +, но я с трудом пытаюсь понять, как я могу вернуть результаты функции обратного вызова в качестве результатов метода поиска. Как это сделать в классе контроллера?

+0

Имейте в виду, что использование async-кода имеет тенденцию создавать собственный асинхронный код. Вероятно, вы разделите свой метод на две части: начальный код, ведущий к асинхронному вызову, и все, что должно выполняться в ответ на этот вызов. Реализуют ли объекты и методы «Задача» или «Задача », используют ли они 'IAsyncResult' или только механизм обратного вызова? –

+0

Я считаю, что lync api использует механизм IAsyncResult – Rookie

+0

Как изменить метод поиска, чтобы вместо этого я возвращал задачу? – Rookie

ответ

1

Если вы хотите использовать асинхронные/ОЖИДАНИЕ шаблона для этого использования Task.FromAsynchttps://msdn.microsoft.com/en-us/library/system.threading.tasks.taskfactory.fromasync(v=vs.110).aspx

Google для примеров. Как это:

public async Task<List<LyncContact>> SearchAsync(string searchKey) 
{ 
    List<LyncContact> contactList = new List<LyncContact>(); 

    Console.WriteLine("Searching for contacts on " + searchKey); 

    var cm = LyncClient.GetClient().ContactManager; 
    var searchResults = await Task<SearchResults>.Factory.FromAsync<String>(
     cm.BeginSearch, 
     cm.EndSearch, searchKey, null); 

    if (searchResults.Contacts.Count > 0) 
    { 

     Console.WriteLine(searchResults.Contacts.Count.ToString() + " found"); 

     foreach (Contact contact in searchResults.Contacts) 
     { 
      String displayName = contact.GetContactInformation(ContactInformationType.DisplayName).ToString(); 
      ContactAvailability currentAvailability = (ContactAvailability)contact.GetContactInformation(ContactInformationType.Availability); 

      Console.WriteLine(
       contact.GetContactInformation(ContactInformationType.DisplayName).ToString() + " " + contact.GetContactInformation(ContactInformationType.Availability).ToString()); 

      LyncContact lyncContact = new LyncContact.Builder().DisplayName("Snehil").Availability("Busy").build(); 

      contactList.Add(lyncContact); 
     } 
    } 

    return contactList 
} 

В контроллере вы затем можете сделать:

public async Task<String> Get(int id) 
{ 
    log.Info("[GET] Search for Lync User: " + id); 

    Lync lync = new Lync(); 

    ////lync.signIn(); 
    Boolean isSignedIn = lync.isUserSignedIn(); 

    if (isSignedIn) 
    { 
     log.Info("User is Signed In"); 
     Console.Write("Enter search key : "); 
     var lyncContacts = await SearchAsync("medina"); 

     log.Info("Results found: " + lyncContacts.Count); 
     return lyncContacts.ToString(); 
    } 
    else 
    { 
     log.Info("User is not Signed In!"); 
     // TODO: Return status 500 
     return "testUser"; 
    } 
    //Console.ReadLine(); 
    //return "testUser"; 
} 

Или вы можете использовать TaskCompletionSource см http://blog.stephencleary.com/2012/07/async-interop-with-iasyncresult.html (старшую должность, но принцип остается в силе

Предупреждение.

Я не могу скомпилировать это, так как у меня нет доступа к библиотекам, которые вы используете. Он должен работать bu т там могут быть некоторые ошибки компиляции

Что это делает

Callbacks не хорошая модель для работы, как вы выяснили. использование Заданий и асинхронная/ожидающая модель намного легче работать. К счастью для вас и для меня, они создали несколько методов, которые могут служить мостом между старой и новой моделью. Используя Task.FromAsync, вы можете преобразовать методы IAsyncResult в более легкую в использовании методологию, основанную на задачах. Стивен Клири написал несколько хороших блогов о них. См. Сообщение, о котором я упоминал ранее.

+0

Я согласен, что это лучший стиль, но библиотека, которую использует Snehil, не имеет методов, возвращающих 'Task' –

+1

@AndySkirrow. Вы правы, но используя эти методы, вы можете их создать. Вот почему Task.Factory.FromAsync для. Сделать мост для методов, которые следуют за шаблоном AsyncCallback. –

+0

Да, согласовано; но я думаю, было бы полезно более подробно рассказать о том, как это работает в ответ. Мое предположение заключается в том, что ОП не осознает TPL (что может быть неправильно). –

0

Похоже, что вы просмотрели свой код с пропущенным кодом, который вы пытались предоставить своего рода обратный вызов для вашей функции Search. Это будет работать, он должен быть типа Action<Microsoft.Lync.Model.SearchResults>

public void Search(string searchKey, Action<SearchResults> callback) 
{ 
    .... 
    LyncClient.GetClient().ContactManager.BeginSearch(
      searchKey, 
      (ar) => 
      { 
       SearchResults searchResults = LyncClient.GetClient().ContactManager.EndSearch(ar); 
       callback(searchResults); 
      }); 
    .... 
} 

Тогда просто раскомментировать код в контроллере:

lync.Search("medina", 
     (lyncContacts) => 
     { 
      log.Debug("Search Results Callback fired!"); 
      log.Info("Results found: " + lyncContacts.AllResults.Count);     
     }); 
+0

Да, я попытался предоставить обратный вызов и вернуть результаты в обратном вызове в коде, который вы показали выше. Но я не уверен, как передать эти результаты WEBAPI ... любые мысли? – Rookie

Смежные вопросы