Асинхронный вызов Silverlight 4 в арсенал World of Warcraft с потоковой передачей XML в C # - PullRequest
0 голосов
/ 24 мая 2010

Я застрял на этом все выходные и с треском провалился!
Пожалуйста, помогите мне вернуть мое здравомыслие !!

Ваш вызов

Для моего первого приложения Silverlight я подумал, что было бы интересно использовать арсенал World of Warcraft, чтобы перечислить персонажей в моей гильдии. Это включает в себя создание асинхронного от Silverlight (дух!) К вооружению WoW, основанном на XML. ПРОСТО EH?

Взгляните на эту ссылку и откройте исходный код. Вы увидите, что я имею в виду: http://eu.wowarmory.com/guild-info.xml?r=Eonar&n=Gifted и Талантливый

Ниже приведен код для получения XML (вызов ShowGuildies справится с возвращенным XML - я проверил это локально и знаю, что он работает).

Мне вообще не удалось получить ожидаемый возвращаемый XML.

Примечания:

  • Если браузер способен преобразовывать XML, он это сделает, в противном случае будет предоставлен HTML. Я думаю, что это проверяет UserAgent
  • Я опытный веб-разработчик asp.net для C #, так что будьте спокойны, если вы начнете говорить о нативном для Windows Forms / WPF
  • Кажется, я не могу установить параметр UserAgent в .net 4.0 - кажется, это не свойство объекта HttpWebRequest по какой-то причине - я думаю, что раньше он был доступен.
  • Silverlight 4.0 (изначально создавался как 3.0 до того, как я обновил установку Silverlight до 4.0)
  • Создано с использованием C # 4.0
  • Пожалуйста, объясните, как будто вы разговариваете с веб-разработчиком, а не с правильным программированием. Lol!

Ниже приведен код - он должен возвращать XML из хранилища wow.

private void button7_Click(object sender, RoutedEventArgs e)
{
   // URL for armoury lookup
                string url = @"http://eu.wowarmory.com/guild-info.xml?r=Eonar&n=Gifted and Talented";

                // Create the web request
                HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(url);

                // Set the user agent so we are returned XML and not HTML
                //httpWebRequest.Headers["User-Agent"] = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0)";

                // Not sure about this dispatcher thing - it's late so i have started to guess.
                Dispatcher.BeginInvoke(delegate()
                {
                    // Call asyncronously
                    IAsyncResult asyncResult = httpWebRequest.BeginGetResponse(ReqCallback, httpWebRequest);

                    // End the response and use the result
                    using (HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.EndGetResponse(asyncResult))
                    {
                        // Load an XML document from a stream
                        XDocument x = XDocument.Load(httpWebResponse.GetResponseStream());

                        // Basic function that will use LINQ to XML to get the list of characters.
                        ShowGuildies(x);
                    }
                });
            }

            private void ReqCallback(IAsyncResult asynchronousResult)
            {
                // Not sure what to do here - maybe update the interface?
            }

Действительно надеюсь, что кто-то там поможет мне!

Спасибо, Мучо! Dan.

PS Да, я заметил иронию в названии гильдии:)

1 Ответ

1 голос
/ 24 мая 2010

Во-первых, Dispatcher.BeginInvoke требуется, только когда вы находитесь в потоке, отличном от потока пользовательского интерфейса (где происходит все, что связано с silverlight / WPF). При событии щелчка вы уже находитесь в потоке пользовательского интерфейса, поэтому нет необходимости вызывать его.

Во-вторых, BeginGetResponse является асинхронной операцией, поэтому после ее завершения она вызовет функцию обратного вызова в другом потоке, здесь ReqCallback. Именно в этом методе вы можете вызвать EndGetResponse. Этот шаблон применяется ко всем BeginX / EndX, которые вы найдете в фреймворке.

Однако, поскольку вы находитесь в другом потоке, вам нужно будет использовать BeginInvoke для отправки метода обратно в поток пользовательского интерфейса.

Код будет выглядеть так:

private void button7_Click(object sender, RoutedEventArgs e) {
    string url = @"http://eu.wowarmory.com/guild-info.xml?r=Eonar&n=Gifted and Talented";
    HttpWebRequest httpWebRequest = (HttpWebRequest) WebRequest.Create(url);
    httpWebRequest.BeginGetResponse(ReqCallback, httpWebRequest);
}

private void ReqCallback(IAsyncResult asyncResult)
{
    HttpWebRequest httpWebRequest = (HttpWebRequest) asyncResult.AsyncState;
    using (HttpWebResponse httpWebResponse = (HttpWebResponse) httpWebRequest.EndGetResponse(asyncResult))
    {
        XDocument x = XDocument.Load(httpWebResponse.GetResponseStream());
        Dispatcher.BeginInvoke((Action) (() => ShowGuildies(x)));
    }
}

Обратите внимание, что вы также можете обрабатывать XML в потоке и использовать диспетчер только для отправки обратно гильдий в UI, чтобы избежать зависания UI, если XML очень длинный для анализа (не должно быть так). 1015 *

Редактировать: Исправлен код. Вам нужно только реализовать ShowGuildies. Что касается подключения к Интернету и задержек, поскольку операция происходит в другом потоке, пользовательский интерфейс не зависает. Вы можете показать анимацию загрузки или что-то еще.

...