Я опубликовал небольшое бесплатное приложение для смартфонов Windows Phone 8 (чтобы познакомиться с С#, поэтому я начинаю программировать). Многие мои пользователи очень довольны функциональностью, но некоторые из них, похоже, продолжают получать случайные сбои (например, в Канаде: http://www.windowsphone.com/en-ca/store/app/picture-of-the -day/fc977a34-c09d-4c70-8a7b-66b6f09ab7f0) Я никогда не испытывал таких сбоев на своих тестовых устройствах и пытался избавиться от них, добавив несколько утверждений try-catch - но безуспешно.
В отчете о сбое говорится следующее:
Frame Image Function Offset
0 system_xml_ni System.Xml.XmlTextReaderImpl.Throw 0x00000036
1 system_xml_ni System.Xml.XmlTextReaderImpl.ParseDocumentContent 0x00000438
2 system_xml_ni System.Xml.XmlTextReaderImpl.Read 0x00000036
3 system_xml_linq_ni System.Xml.Linq.XDeclaration..ctor 0x00000072
4 system_xml_linq_ni System.Xml.Linq.XDocument.Load 0x0000010a
5 system_xml_linq_ni System.Xml.Linq.XDocument.Load 0x00000042
6 system_xml_linq_ni System.Xml.Linq.XDocument.Load 0x00000006
7 phoneapp1_ni PhoneApp1.MainPage+__c__DisplayClassb._doLoadURL_b__6 0x00000040
8 system_net_ni System.Net.WebClient.OnOpenReadCompleted 0x00000010
9 system_net_ni System.Net.WebClient.OpenReadOperationCompleted 0x00000034'
Фактический код, который, как я думаю, отвечает:
try
{
WebClient client = new WebClient();
client.OpenReadAsync(new Uri(Url, UriKind.Absolute));
client.OpenReadCompleted += (sender, e) =>
{
if (e.Error != null)
{
return;
}
else
{
System.Xml.Linq.XDocument xmlDoc = XDocument.Load(e.Result);
IEnumerable<string> strTestURL = from node in xmlDoc.Descendants("url") select node.Value;
IEnumerable<string> strTestDescription = from node in xmlDoc.Descendants("copyright") select node.Value;
IEnumerable<string> strTestDate = from node in xmlDoc.Descendants("enddate") select node.Value;
string strURL = "http://www.bing.com" + strTestURL.First();
strURL = strURL.Replace("1366x768", "800x480");
Global.URL1 = strURL;
Global.URLs[i] = strURL;
Global.Descriptions[i] = strTestDescription.First();
Uri Uri = new Uri(Global.URLs[i], UriKind.Absolute);
Imageallgemein.Source = new BitmapImage(Uri);
Imageallgemein.Tap += new EventHandler<System.Windows.Input.GestureEventArgs>(onImageTap);
Imageallgemein.Hold += new EventHandler<System.Windows.Input.GestureEventArgs>(onImageTap);
Description.Text = Global.Descriptions[i];
string Year = strTestDate.First().Substring(0, 4);
string Month = strTestDate.First().Substring(4, 2);
string Day = strTestDate.First().Substring(6, 2);
Date.Text = Day + "." + Month + "." + Year;
}
};
}
catch
{
MessageBox.Show(AppResources.Abort, AppResources.msgBoxUrlLoadError, MessageBoxButton.OK);
}
try-catch, кажется, не имеет никакого эффекта, и я надеюсь, что кто-то сможет решить это для меня.
Должна быть какая-то проблема с XML, предоставленным e.Result
. Подробности об этом могут быть в сообщении XmlException
но вы включили только часть трассировки стека.
Вам нужно будет выяснить, в чем проблема в первую очередь, и вам, вероятно, придется добавить некоторые записи о том, что происходит до того, как вы вызываете XDocument.Load
если вы не можете воспроизвести проблему в своей собственной системе.
Вы также можете добавить обработчик исключений, но это не устраняет проблему, но делает ваше приложение более надежным и позволяет ему немного улучшить интерфейс пользователя, если произойдет что-то неожиданное. Вы сделали добавление обработчика исключений вокруг вызовов методам WebClient
но вы не client.OpenReadCompleted
исключения, вызванные обработчиком для client.OpenReadCompleted
. client.OpenReadCompleted
. Это асинхронный обратный вызов, который будет выполняться в потоке threadpool, и любые неперехваченные исключения, создаваемые этим потоком, прекратят ваше приложение.
Вам нужно обработать исключение с помощью кода следующим образом:
client.OpenReadCompleted += (sender, e) =>
{
try
{
if (e.Error != null)
{
return;
}
else
....
}
catch (Exception ex)
{
.... log and report the exception to allow the app to continue
}
}
И если вы решите добавить журнал в свое приложение, это будет очень полезно для вас, если вы зарегистрируете весь текст, возвращенный ex.ToString()
. Это даст вам хорошее текстовое описание проблемы, включая внутренние исключения и полные следы стека.
Обычно является хорошей практикой делать catch(Exception)
, в вашем случае catch(system.xml.XmlException)
. Однако поставите try-catch внутри вашего блока else, потому что это асинхронное событие, и если произойдет какое-то исключение внутри этого исключения, он не будет зацепиться:
try
{
WebClient client = new WebClient();
client.OpenReadAsync(new Uri(Url, UriKind.Absolute));
client.OpenReadCompleted += (sender, e) =>
{
if (e.Error != null)
{
return;
}
else
{
try
{
System.Xml.Linq.XDocument xmlDoc = XDocument.Load(e.Result);
IEnumerable<string> strTestURL = from node in xmlDoc.Descendants("url") select node.Value;
IEnumerable<string> strTestDescription = from node in xmlDoc.Descendants("copyright") select node.Value;
IEnumerable<string> strTestDate = from node in xmlDoc.Descendants("enddate") select node.Value;
string strURL = "http://www.bing.com" + strTestURL.First();
strURL = strURL.Replace("1366x768", "800x480");
Global.URL1 = strURL;
Global.URLs[i] = strURL;
Global.Descriptions[i] = strTestDescription.First();
Uri Uri = new Uri(Global.URLs[i], UriKind.Absolute);
Imageallgemein.Source = new BitmapImage(Uri);
Imageallgemein.Tap += new EventHandler<System.Windows.Input.GestureEventArgs>(onImageTap);
Imageallgemein.Hold += new EventHandler<System.Windows.Input.GestureEventArgs>(onImageTap);
Description.Text = Global.Descriptions[i];
string Year = strTestDate.First().Substring(0, 4);
string Month = strTestDate.First().Substring(4, 2);
string Day = strTestDate.First().Substring(6, 2);
Date.Text = Day + "." + Month + "." + Year;
}
catch (XmlException)
{
MessageBox.Show(AppResources.Abort, AppResources.msgBoxUrlLoadError, MessageBoxButton.OK);
}
}
};
}
catch (Exception)
{
MessageBox.Show(AppResources.Abort, AppResources.msgBoxUrlLoadError, MessageBoxButton.OK);
}