2011-03-14 2 views
1

J'ai un objet qui télécharge un fichier à partir d'un serveur, l'enregistre dans un stockage isolé de manière asynchrone et fournit une méthode GetData pour récupérer les données. Est-ce que j'utiliser unVerrouillage avec httpwebrequest asynchrone

IsolatedStorageFile storageObj; //initialized in the constructor 

lock(storageObj) 
{ 
    //save code 
} 

Dans la réponse et

lock(storageObj) 
{ 
    //load code 
} 

Dans la méthode GetData?

Edit: Je vais donner un peu de contexte ici. L'application (pour Windows Phone) doit télécharger et mettre en cache plusieurs fichiers d'un serveur, j'ai donc créé un type qui prend 2 chaînes (un uri et un nom de fichier), envoie des données à partir de l'uri donné et l'enregistre . Le même objet possède également la méthode get data. Voici le code (un peu simplifié)

public class ServerData: INotifyPropertyChanged 
{ 
    public readonly string ServerUri; 
    public readonly string Filename; 
    IsolatedStorageFile appStorage; 

    DownloadState _downloadStatus = DownloadState.NotStarted; 
    public DownloadState DownloadStatus 
    { 
     protected set 
     { 
      if (_downloadStatus == value) return; 
      _downloadStatus = value; 
      OnPropertyChanged(new PropertyChangedEventArgs("DownloadStatus")); 
     } 
     get { return _downloadStatus; } 
    } 

    public ServerData(string serverUri, string filename) 
    { 
     ServerUri = serverUri; 
     Filename = filename; 
     appStorage = IsolatedStorageFile.GetUserStoreForApplication(); 
    } 
    protected virtual void OnPropertyChanged(PropertyChangedEventArgs args) 
    { 
     if (PropertyChanged != null) 
      PropertyChanged(this, args); 
    } 

    public void RequestDataFromServer() 
    { 
     DownloadStatus = DownloadState.Downloading; 
    //this first bit adds a random unused query to the Uri, 
    //so Silverlight won't cache the request 
     Random rand = new Random(); 
     StringBuilder uriText = new StringBuilder(ServerUri); 
     uriText.AppendFormat("?YouHaveGotToBeKiddingMeHack={0}", 
          rand.Next().ToString()); 
     Uri uri = new Uri(uriText.ToString(), UriKind.Absolute); 
     HttpWebRequest serverRequest = (HttpWebRequest)WebRequest.Create(uri); 
     ServerRequestUpdateState serverState = new ServerRequestUpdateState(); 
     serverState.AsyncRequest = serverRequest; 
     serverRequest.BeginGetResponse(new AsyncCallback(RequestResponse), 
      serverState); 
    } 

    void RequestResponse(IAsyncResult asyncResult) 
    { 
     var serverState = (ServerRequestUpdateState)asyncResult.AsyncState; 
     var serverRequest = (HttpWebRequest)serverState.AsyncRequest; 
     Stream serverStream; 
     try 
     { 
      // end the async request 
      serverState.AsyncResponse = 
       (HttpWebResponse)serverRequest.EndGetResponse(asyncResult); 
      serverStream = serverState.AsyncResponse.GetResponseStream(); 
      Save(serverStream); 
      serverStream.Dispose(); 
     } 
     catch (WebException) 
     { 
      DownloadStatus = DownloadState.Error; 
     } 

     Deployment.Current.Dispatcher.BeginInvoke(() => 
     { 
      DownloadStatus = DownloadState.FileReady; 
     }); 
    } 

    void Save(Stream streamToSave) 
    { 
     StreamReader reader = null; 
     IsolatedStorageFileStream file; 
     StreamWriter writer = null; 
     reader = new StreamReader(streamToSave); 

     lock (appStorage) 
     { 
      file = appStorage.OpenFile(Filename, FileMode.Create); 
      writer = new StreamWriter(file); 
      writer.Write(reader.ReadToEnd()); 
      reader.Dispose(); 
      writer.Dispose(); 
     } 
    } 

    public XDocument GetData() 
    { 
     XDocument xml = null; 
     lock(appStorage) 
     { 
      if (appStorage.FileExists(Filename)) 
      { 
       var file = appStorage.OpenFile(Filename, FileMode.Open); 
       xml = XDocument.Load(file); 
       file.Dispose(); 
      } 
     } 
     if (xml != null) 
      return xml; 
     else return new XDocument(); 
    } 
} 
+0

si c'est le cas pourquoi ne pas le faire de manière synchrone? –

+0

Cela bloquerait le fil de l'interface utilisateur –

Répondre

1

Votre question ne fournit pas énormément de contexte, et avec la quantité d'information donné aux gens pourraient être tentés de vous dire simplement oui, peut-être avec une petite, mais pertinente ajouts. Pratique généralement verrouille se produire sur une instance d'un object dédié, en étant sûr de rester loin de verrouiller sur this puisque vous verrouillez l'instance entière de l'objet courant vers le bas, ce qui est à peine, si jamais l'intention - mais, dans Dans votre cas, nous ne savons pas à juste titre dans quelle mesure, cependant, je ne pense pas que verrouiller votre instance de stockage est la voie à suivre.

En outre, puisque vous mentionnez l'interaction client/serveur, ce n'est pas aussi simple.

En fonction de la charge et de nombreux autres facteurs, vous pouvez fournir plusieurs lectures du fichier à partir du serveur, mais seulement une seule écriture à la fois sur le client en cours de téléchargement; à cet effet, je recommande d'utiliser la classe ReaderWriterLockSlim, qui expose TryEnterReadLock, TryEnterWriteLock et les méthodes de publication correspondantes.

Pour plus d'informations sur cette classe, voir this MSDN link.

Aussi, pensez à utiliser try, catch et finally lors du codage dans le cadre d'une serrure, libérant toujours le verrou dans le bloc finally.

+0

Merci pour le conseil, je vais élargir ma question. –

+0

Oh, et avant que j'oublie, il n'y a pas d'écriture sur le serveur dans cette application, les arguments pour les données demandées est strictement dans l'uri. –

+0

Malheureusement, ReaderWriterLockSlim n'est pas dans Silverlight. –

0

Quelle classe contient ce code? Cela compte, car c'est important si cela est créé plus d'une fois. S'il est créé une fois dans la durée de vie du processus, vous pouvez le faire, sinon vous devez verrouiller une instance d'objet statique. Je crois cependant que c'est une bonne pratique de créer un objet séparé qui est utilisé uniquement dans le but de verrouillage, j'ai oublié pourquoi. E.g .:

IsolatedStorageFile storageObj; //initialized in the constructor 
(static) storageObjLock = new object(); 
... 
// in some method 
lock(storageObjLock) 
{ 
    //save code 
}