2011-03-14 71 views
1

我有从服务器下载的文件时,它保存到独立存储异步并提供GetData方法来检索数据的对象。我会用一个异步HttpWebRequest的锁定

IsolatedStorageFile storageObj; //initialized in the constructor 

lock(storageObj) 
{ 
    //save code 
} 

在响应和

lock(storageObj) 
{ 
    //load code 
} 

在GetData方法?

编辑:我会在这里提供一些背景。 应用程序(用于Windows Phone)需要从服务器下载并缓存多个文件,因此我创建了一个需要2个字符串(一个uri和一个文件名)的类型,从给定的uri发送数据并保存它。同一个对象也有get数据方法。下面的代码(简化一点)

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

如果是这种情况,为什么不同步做? – 2011-03-14 23:54:50

+0

这将阻止用户界面线程 – 2011-03-16 18:39:51

回答

1

你的问题不提供非常多的情况下,并与给定信息的人的数量可能倾向于简单地告诉你,是的,也许有小,但相关补充。

实践一般认为锁定发生在一个专门的object一个实例,是一定要从锁定在this望而却步,因为你锁定当前对象下来,这是几乎整个实例,如果有的话的意图 - 但是,在你的情况,我们不能完全正确地知道,但是,我几乎不认为锁定你的存储实例是一条路。

此外,由于你提到的客户端和服务器的交互,它不是直线前进。

根据负载等诸多因素的影响,你可能想提供从服务器,但只有在任一周时间被下载客户端上的单次写入的文件的大量读取;为此,我建议使用ReaderWriterLockSlim类,该类提供TryEnterReadLock,TryEnterWriteLock和相应的发布方法。

有关此类的详细信息,请参阅this MSDN link

此外,请记住锁定的范围内进行编码时,总是释放在finally块锁使用trycatchfinally

+0

感谢您的建议,我会扩展我的问题。 – 2011-03-15 01:37:15

+0

哦,在我忘记之前,在这个应用程序中没有写入服务器的请求,所请求数据的参数严格在uri中。 – 2011-03-15 02:36:51

+0

不幸的是,ReaderWriterLockSlim不在Silverlight中。 – 2011-03-16 02:11:10

0

什么类包含此代码?如果它不止一次被创建,这很重要。如果它在进程的一生中创建一次,则可以执行此操作,否则应锁定对象实例的静态。

我相信,虽然它是很好的做法,打造了仅用于锁定的目的,一个单独的对象,我忘了为什么。例如:

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