Блокировка с помощью асинхронного httpwebrequest - PullRequest
1 голос
/ 15 марта 2011

У меня есть объект, который загружает файл с сервера, асинхронно сохраняет его в изолированном хранилище и предоставляет метод GetData для извлечения данных.Буду ли я использовать

IsolatedStorageFile storageObj; //initialized in the constructor

lock(storageObj)
{
   //save code
}

в ответе и

lock(storageObj)
{
   //load code
}

в методе GetData?

Правка: здесь я приведу некоторый контекст.Приложение (для Windows Phone) должно загружать и кэшировать несколько файлов с сервера, поэтому я создал тип, который принимает 2 строки (URI и имя файла), отправляет данные из данного URI и сохраняет их.Этот же объект также имеет метод get data.Вот код (немного упрощенный)

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

Ответы [ 2 ]

1 голос
/ 15 марта 2011

Ваш вопрос не дает очень много контекста, и с количеством информации, которую дают люди, могут быть склонны просто сказать вам, да, может быть, с небольшими, но подходящими дополнениями.

Практика обычно видит блокировкупроисходят в случае экземпляра выделенного object, обязательно избегая блокировки на this, так как вы блокируете весь экземпляр текущего объекта, что едва ли является намерением, но в вашем случае мыоднако, я не думаю, что в полной мере знаю, но вряд ли стоит блокировать экземпляр хранилища.

Кроме того, поскольку вы упоминаете взаимодействие между клиентом и сервером, это не так просто.

В зависимости от нагрузки и многих других факторов, вы можете захотеть обеспечить много чтений файла с сервера, но в то же время только одну запись на клиенте, который загружает;для этой цели я бы рекомендовал использовать класс ReaderWriterLockSlim, который предоставляет TryEnterReadLock, TryEnterWriteLock и соответствующие методы выпуска.

Более подробную информацию об этом классе см. в этой ссылке MSDN .

Кроме того, не забывайте использовать try, catch и finally при кодировании в пределах области блокировки, всегда снимая блокировку в блоке finally.

0 голосов
/ 15 марта 2011

Какой класс содержит этот код? Это важно, так как это важно, если он создается несколько раз. Если он создан один раз за время жизни процесса, вы можете сделать это, если нет, вам нужно заблокировать статический экземпляр объекта.

Хотя я считаю, что хорошей практикой является создание отдельного объекта, который используется только для блокировки, я забыл почему. E.g.:

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