проблемы в Silverlight 4 при использовании обратных вызовов Action для проверки успешной загрузки файла - PullRequest
1 голос
/ 04 января 2011

Таким образом, асинхронное требование для silverlight заканчивается каким-то действительно запутанным кодом !!

Я загружаю файл точно так же, как этот ответ предлагает.

Разница в том, что я отправляю файл в метод действия MVC.Все работает с файлом, за исключением того, что, как я прокомментировал в нижней части этого ответа, я не получаю никакого обратного вызова, когда файл НЕ успешно загружен.

Итак, я создал другой метод действия в своем приложении mvc (Services/CheckForFile/{id}), и он возвращает строку в зависимости от того, найден ли файл.

Теперь, как и когда я вызываю этот mvcПроблема в методе действия:

  void DoUpload() { //Gets call on BtnUpload.Click
              //opn is an OpenFileDialog
            up.UploadFile(_filename, opn.File.OpenRead(),
                e =>
                {
                 //do some ui stuff here.
                  BeginCheck();// calling this causes PROBLEMS!  
                });
    }
    private void BeginCheck()
    {
        Uploader up = new Uploader();
        up.CheckForFile(_filename, success =>
        {
            if (!success)
            {
                MessageBox.Show("There was problem uploading the file. Please try again", "Error", MessageBoxButton.OK);
            }
        });
    }

Проблема в следующем: при запуске функции BeginCheck () файл по какой-либо причине НИКОГДА не загружается!Если я это прокомментирую, это так !?Кажется, что BeginCheck () работает во время загрузки или что-то?Разве он не должен запускаться после !?

Как / где я бы вызвал BeginCheck () после загрузки, чтобы убедиться, что файл был загружен?

Вот как я определилкласс Uploader:

 public class Uploader
    {
        public void UploadFile(string fileName, Stream data, Action<Exception> callback)
        {
            UriBuilder ub = new UriBuilder(_mvcurl+"Services/UploadFile/" + fileName);
            WebClient c = new WebClient();
            c.OpenWriteCompleted += (sender, e) =>
            {
                try
                {
                    PushData(data, e.Result);
                    e.Result.Close();
                    data.Close();  //this does not block.
                    callback(null);//this ALWAYS hits!
                }
                catch (Exception err)
                {
                    if (callback != null)
                    {
                        callback(err);
                    }
                }
            };
            c.OpenWriteAsync(ub.Uri);
        }
        public void CheckForFile(string filename, Action<bool> callback)
        {
            UriBuilder ub = new UriBuilder(_mvcurl+"Services/CheckForFile/" + fileName);
            WebClient c = new WebClient();
            c.OpenReadCompleted += (sender, e) =>
                {
                    using (StreamReader sw = new StreamReader(e.Result))
                    {
                        if (sw.ReadToEnd().Equals("Found", StringComparison.InvariantCultureIgnoreCase))
                        {
                            callback(true);
                        }
                        else
                        {
                            callback(false);
                        }
                    }
                };
            c.OpenReadAsync(ub.Uri);
        }
        private void PushData(Stream input, Stream output)
        {//4KB is not a limitation. We only copy 4Kb at a time from in to out stream
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = input.Read(buffer, 0, buffer.Length)) != 0)
            {
                output.Write(buffer, 0, bytesRead);
            }
        }
    }

1 Ответ

1 голос
/ 04 января 2011

Мне стыдно сказать, что мой первоначальный ответ, на который вы ссылаетесь, не совсем точен. Кажется, это работает для того, что хотел ОП, но на самом деле код не блокируется в тот момент, когда я думал, что это сработало. В действительности то, что вы на самом деле ищете, - это событие WriteStreamClosed, здесь вы можете обнаружить любой сбой запроса.

Вот исправленная версия, которая работает так, как вы ожидаете: -

        public void UploadFile(string fileName, Stream data, Action<Exception> callback)
        {
            UriBuilder ub = new UriBuilder(_mvcurl+"Services/UploadFile/" + fileName);
            WebClient c = new WebClient();
            c.OpenWriteCompleted += (sender, e) =>
            {
                try
                {
                    PushData(data, e.Result);
                    e.Result.Close();
                    data.Close();  //this does not block.
                }
                catch (Exception err)
                {
                    if (callback != null)
                        callback(err);
                }
            };
            c.WriteStreamClosed += (sender, e) =>
            {
                if (callback != null)
                    callback(e.Error);
            }
            c.OpenWriteAsync(ub.Uri);
        }

Теперь ваша BeginCheck будет работать только после ответа сервера на загрузку файла.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...