2009-03-09 6 views
0

Im klassischen ASP.NET würde ich Daten von einem Web-Service in Basisklasse Eigenschaft extrahiert bestehen wie folgt:Persisted Eigenschaften - asynchron

private string m_stringData; 
    public string _stringData 
    { get { 
      if (m_stringData==null) 
       { 
        //fetch data from my web service 
        m_stringData = ws.FetchData() 
       } 
      return m_stringData; 
     } 
    } 

So kann ich einfach Bezug auf _stringData machen konnte und wissen, dass Ich würde immer die Daten erhalten, nach denen ich suchte (vielleicht benutzte ich manchmal den Sitzungszustand als einen Speicher anstelle einer privaten Mitgliedsvariablen).

In Silverlight mit einem WCF kann ich isolierter Speicher als persistance-Mechanismus verwenden, aber der Serviceaufruf kann nicht so erfolgen, da ein WCF-Dienst asynchron aufgerufen werden muss.

Wie kann ich den Serviceaufruf aufrufen und die Antwort in einer Methode abrufen?

Danke, Mark

Antwort

0

In Ihrer Methode, rufen Sie den Service-Aufruf asynchron und einen Rückruf registrieren, die ein Flag setzt. Nachdem Sie die Methode aufgerufen haben, geben Sie eine busy/wait-Schleife ein und überprüfen Sie das Flag regelmäßig, bis das Flag gesetzt ist, das anzeigt, dass die Daten zurückgegeben wurden. Der Callback sollte das Backing-Feld für Ihre Methode festlegen und Sie sollten es zurückgeben können, sobald Sie feststellen, dass das Flag für Erfolg gesetzt wurde. Sie müssen auch über das Versagen besorgt sein. Wenn es möglich ist, mehrere Aufrufe Ihrer Methode von verschiedenen Threads zu erhalten, müssen Sie auch einige Sperren verwenden, um Ihren Code threadsicher zu machen.

EDIT

Eigentlich ist die Belegt/Schleife warten ist wahrscheinlich nicht der richtige Weg zu gehen, wenn die Web-Service-BeginGetData/EndGetData Semantik unterstützt. Ich habe einen Blick auf meinen Code geworfen, wo ich etwas Ähnliches mache, und ich benutze WaitOne, um einfach auf das asynchrone Ergebnis zu warten und es dann abzurufen. Wenn Ihr Web-Service dies nicht unterstützt, dann werfen Sie einen Thread.Sleep - sagen wir für 50-100ms - in Ihre Warteschleife, um Zeit für die Ausführung anderer Prozesse zu haben.

Beispiel aus meinem Code:

IAsyncResult asyncResult = null; 
try 
{ 
    asyncResult = _webService.BeginGetData(searchCriteria, null, null); 
    if (asyncResult.AsyncWaitHandle.WaitOne(_timeOut, false)) 
    { 
     result = _webService.EndGetData(asyncResult); 
    } 
} 
catch (WebException e) 
{ 
    ...log the error, clean up... 
} 
+0

Danke, dass Sie sich die Zeit genommen haben, zu antworten, aber ich habe das vorher versucht und festgestellt, dass meine Warteschleife {do ​​stuff} while (blnWaiting == true)} sperrte den Thread, so dass die Flagge nie gesetzt wurde . Ich bin in diesem "Kommentar" auf 300 Zeichen beschränkt, kann also nicht den vollständigen Code zeigen, kannst du ein Beispiel geben? Danke, Mark –

+0

Ich habe ein Beispiel aus der Art hinzugefügt, wie ich es tatsächlich mache - was anders ist als das, was ich beschrieben habe. Abhängig von Ihrem Web-Service kann es sein oder nicht. – tvanfosson

+0

Ja, das sieht nach dem aus, was ich brauche. Ich werde das umsetzen und sehen, wie ich gehe. Danke für deine Hilfe. –

0

Danke für Ihre Hilfe tvanfosson. Ich folgte Ihren Code und habe auch eine Pseudo-ähnliche Lösung, die meine Bedürfnisse erfüllt genau einen Lambda-Ausdruck mit:

private string m_stringData; 
public string _stringData{  
get 
    { 
    //if we don't have a list of departments, fetch from WCF 
     if (m_stringData == null) 
     { 
      StringServiceClient client = new StringServiceClient(); 
      client.GetStringCompleted += 
       (sender, e) => 
       { 
        m_stringData = e.Result; 
       }; 
      client.GetStringAsync(); 
     } 
     return m_stringData; 
    } 
} 

EDIT

Oops ... eigentlich das nicht funktioniert entweder :-( Ich endete damit, die Anrufe asynchron zu machen und meine Programmierlogik zu ändern, um MVVM-Muster und mehr Bindung zu verwenden