2016-09-20 3 views
0

Ich bin ein Neuling zu C# & Ich versuche, das Lync SDK zu verwenden, um programmgesteuert nach einem Lync-Benutzer zu suchen, um ihren Status zu erhalten. Ich bin nicht sicher, wie die Ergebnisse an die Webservice-Antwort übergeben werden, wenn der asynchrone Rückruf ausgeführt wird.C# Wie zeichne ich asynchrone Ergebnisse auf?

Dies ist der Code:

Webservice-Controller GET Endpunkt:

 // 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"; 
    } 

Die obige Methode ruft das Business Service lync.search (..), die wie folgt lautet:

 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); 
    } 

Ich habe versucht, Task + zu verwenden, aber es fällt mir schwer herauszufinden, wie ich die Ergebnisse aus der Callback-Funktion als Ergebnis der Suchmethode zurückgeben kann. Wie erfasse ich das in der Controller-Klasse?

+0

Bitte beachten Sie, dass die Verwendung von Async-Code eine Tendenz hat, Ihren eigenen Code async zu machen. Wahrscheinlich werden Sie Ihre Methode in zwei Teile aufteilen, den ursprünglichen Code, der zum asynchronen Aufruf führt, und was auch immer als Antwort auf diesen Aufruf ausgeführt werden sollte. Liefern die betreffenden Objekte und Methoden "Task" oder "Task " zurück, verwenden sie "IAsyncResult" oder nur einen Callback-Mechanismus? –

+0

Ich glaube, dass die Lync API den IAsyncResult-Mechanismus verwendet – Rookie

+0

Wie ändere ich die Suchmethode, so dass ich stattdessen eine Aufgabe zurückgibt? – Rookie

Antwort

1

Wenn Sie das async/await Muster für diese Anwendung nutzen möchten Task.FromAsynchttps://msdn.microsoft.com/en-us/library/system.threading.tasks.taskfactory.fromasync(v=vs.110).aspx

Google für Beispiele. Wie folgt aus:

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 
} 

In der Steuerung können Sie dann tun:

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"; 
} 

Oder Sie können ein TaskCompletionSource verwenden, finden Sie http://blog.stephencleary.com/2012/07/async-interop-with-iasyncresult.html (ältere Post, aber grundsätzlich ist immer noch gültig

Warnung.

Ich kann das nicht kompilieren, da ich keinen Zugriff auf die Bibliotheken habe, die Sie verwenden t es könnte einige kompilieren sein Fehler

Was es

Rückrufe sind kein schönes Modell mit zur Arbeit macht, wie Sie herausgefunden haben. Mit Tasks und dem async/await-Modell können Sie viel einfacher arbeiten. Zum Glück für Sie und mich haben sie mehrere Methoden geschaffen, die als Brücke zwischen dem alten und dem neuen Modell dienen können. Mit Task.FromAsync können Sie IAsyncResult-Methoden in eine einfacher zu verwendende aufgabenbasierte Methode umwandeln. Stephen Cleary hat einige nette Blogs über sie geschrieben. Siehe den Beitrag, den ich bereits erwähnt habe.

+0

Ich stimme zu, dass dies ein besserer Stil ist, aber die Bibliothek, die Snehil verwendet, hat keine Methoden, die 'Task's zurücksenden –

+1

@AndySkirrow Sie sind richtig, aber mit diesen Methoden können Sie eine erstellen. Deshalb ist Task.Factory.FromAsync für. So erstellen Sie eine Brücke für Methoden, die dem AsyncCallback-Muster folgen. –

+0

Ja, einverstanden; aber ich denke, es wäre nützlich, deutlicher zu machen, wie das in einer Antwort funktioniert. Ich gehe davon aus, dass der OP die TPL nicht kennt (was vielleicht falsch ist). –

0

Es sieht so aus, als ob Sie, indem Sie Ihren auskommentierten Code betrachten, versucht haben, eine Art Callback für Ihre Search-Funktion bereitzustellen. Das würde funktionieren, ist es vom Typ Action<Microsoft.Lync.Model.SearchResults>

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

Dann Kommentar- Sie einfach den Code in Ihrem Controller:

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

Ja, ich habe versucht, einen Rückruf bereitzustellen, und die Ergebnisse werden im Rückruf im oben angezeigten Code angezeigt. Aber ich bin mir nicht sicher, wie ich diese Ergebnisse an die WEBAPI weiterleiten soll ... irgendwelche Gedanken? – Rookie