2011-03-14 4 views
1

서버에서 파일을 다운로드하고 비동기 적으로 격리 저장소에 저장하고 GetData 메서드를 사용하여 데이터를 검색하는 개체가 있습니다. 나는 GetData 메서드에서는 응답에서비동기 httpwebrequest로 잠그기

IsolatedStorageFile storageObj; //initialized in the constructor 

lock(storageObj) 
{ 
    //save code 
} 

lock(storageObj) 
{ 
    //load code 
} 

를 사용 하시겠습니까?

편집 : 여기에 몇 가지 상황을 알려 드리겠습니다. 응용 프로그램 (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

동기식으로 전송하지 않는 이유는 무엇입니까? –

+0

그게 UI 스레드를 차단할 것입니다 –

답변

1

(조금 간체) 코드는하지만 관련 추가.

연습에서는 일반적으로 object 전용 인스턴스에서 잠금이 발생하며 현재 오브젝트의 전체 인스턴스를 잠그므로 this에 잠글 수 없다는 사실을 알고 있습니다. 귀하의 경우, 우리는 제대로 이해하지 못하고 있지만, 스토리지 인스턴스를 잠그는 것이 최선의 방법이라고 생각하지 않습니다.

또한 클라이언트와 서버의 상호 작용에 대해 언급 했으므로 간단하지 않습니다.

부하 및 기타 요인에 따라 서버에서 파일을 여러 번 읽으면되지만 다운로드하는 클라이언트에서는 한 번에 한 번만 쓸 수 있습니다. 이를 위해 ReaderWriterLockSlim 클래스를 사용하는 것이 좋습니다.이 클래스는 TryEnterReadLock, TryEnterWriteLock 및 해당 릴리스 방법을 제공합니다.

이 클래스에 대한 자세한 내용은 this MSDN link을 참조하십시오.

또한, 로크의 범위 내에서 항상 코딩 finally 블록의 잠금을 해제 할 때 try, catchfinally을 사용하여 기억한다.

+0

조언 주셔서 감사, 내 질문을 확장 해 드리겠습니다. –

+0

아, 그리고 잊지하기 전에,이 응용 프로그램에서 서버에 쓰기가 없습니다, 요청한 데이터에 대한 인수가 엄격히 uri에 있습니다. –

+0

슬프게도, ReaderWriterLockSlim은 Silverlight에 없습니다. –

0

이 코드가 들어있는 클래스는 무엇입니까? 그것이 한 번 이상 만들어지면 중요합니다. 프로세스의 평생에 한 번 생성 된 경우 수행 할 수 있습니다. 그렇지 않으면 정적 개체 인스턴스를 잠 가야합니다.

잠금 목적으로 만 사용되는 별도의 개체를 만드는 것이 좋지만 나는 그 이유를 잊어 버렸습니다. 예 :

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