#c# #visual-studio-2010 #windows-phone-7 #live-tile
#c# #visual-studio-2010 #windows-phone-7 #живая плитка
Вопрос:
Первый пост здесь, извините, что начал с вопросов.
В моем приложении для Windows Phone 7 у меня есть рабочий livetile, который запускается фоновым агентом. Но как я могу изменить код, чтобы тайм-ауты httpwebrequest истекали через 10 секунд?
Заранее спасибо.
protected override void OnInvoke(ScheduledTask task)
{
//TODO: Add code to perform your task in background
var request = (HttpWebRequest)WebRequest.Create(
new Uri("site.com"));
request.BeginGetResponse(r =>
{
var httpRequest = (HttpWebRequest)r.AsyncState;
var httpResponse = (HttpWebResponse)httpRequest.EndGetResponse(r);
using (var reader = new StreamReader(httpResponse.GetResponseStream()))
{
var response = reader.ReadToEnd();
Deployment.Current.Dispatcher.BeginInvoke(new Action(() =>
{
string strResult = response;
/// If application uses both PeriodicTask and ResourceIntensiveTask
if (task is PeriodicTask)
{
// Execute periodic task actions here.
ShellTile TileToFind = ShellTile.ActiveTiles.FirstOrDefault(x => x.NavigationUri.ToString().Contains("TileID=2"));
if (TileToFind != null)
{
StandardTileData NewTileData = new StandardTileData
{
BackgroundImage = new Uri("Pin-to-start.png", UriKind.Relative),
Title = strResult,
Count = null
};
TileToFind.Update(NewTileData);
}
}
else
{
// Execute resource-intensive task actions here.
}
NotifyComplete();
}));
}
}, request);
}
Ответ №1:
Вот копирование / вставка из кода, который я использую в одном из своих приложений. Соединение будет прервано через 60 секунд.
private static void DoWebRequest(string uri)
{
string id = "my_request";
Timer t = null;
int timeout = 60; // in seconds
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Accept = "*/*";
request.AllowAutoRedirect = true;
// disable caching.
request.Headers["Cache-Control"] = "no-cache";
request.Headers["Pragma"] = "no-cache";
t = new Timer(
state =>
{
if (string.Compare(state.ToString(), id, StringComparison.InvariantCultureIgnoreCase) == 0)
{
logger.Write("Timeout reached for connection [{0}], aborting download.", id);
request.Abort();
t.Dispose();
}
},
id,
timeout * 1000,
0);
request.BeginGetResponse(
r =>
{
try
{
if (t != null)
{
t.Dispose();
}
// your code for processing the results
}
catch
{
// error handling.
}
},
request);
}
catch
{
}
}
Комментарии:
1. Спасибо! Должен ли я добавить весь синтаксический анализ, а также фрагменты в «запрос. BeginGetResponse(…»?
2. да, вы можете просто оставить его там, но убедитесь, что вы утилизируете t (таймер) в начале BeginGetResponse .
3. Хорошо, итак, я беру ваш код и заменяю свой код до тех пор, пока «запрос. Начало ответа»? Я новичок, поэтому прошу прощения за основные вопросы 🙂 Я пытался это сделать, но получаю следующие ошибки: имя ‘timeout’ не существует в текущем контексте Имя ‘t’ не существует в текущем контексте
4. Хорошо, я опубликую более подробный пример через секунду. подождите.
5. Большое вам спасибо! Я использовал ваш код как своего рода оболочку, а затем добавил весь свой старый код после t.Dispose() . Сейчас я тестирую и думаю, что это работает. Я проверю после того, как мой телефон будет переведен в режим ожидания на ночь, если обновление живой плитки продолжится. Куда я должен поместить вызов NotifyComplete()?
Ответ №2:
Но как я могу изменить код, чтобы тайм-ауты httpwebrequest истекали через 10 секунд?
Вы имеете в виду, что он будет вызываться NotifyComplete()
независимо от тайм-аутов?-) Проблема в том, что через 15 секунд задача завершается и отключается до тех пор, пока пользователь не запустит ее повторно (внутри вашего приложения).
Я бы рекомендовал использовать TPL для Silverlight и использовать возможность использовать задачи для установки времени ожидания.
Что-то вроде:
protected override void OnInvoke(ScheduledTask task)
{
var fetchTask = FetchData(TimeSpan.FromSeconds(10));
fetchTask.ContinueWith(x =>
{
Deployment.Current.Dispatcher.BeginInvoke(new Action(() =>
{
string strResult = x.Resu< // mind you, x.Result will be "null" when a timeout occours.
...
NotifyComplete();
}));
});
}
private Task<string> FetchData(TimeSpan timeout)
{
var tcs = new TaskCompletionSource<string>();
var request = (HttpWebRequest)WebRequest.Create(new Uri("site.com"));
Timer timer = null;
timer = new Timer(sender =>
{
tcs.TrySetResult(null);
timer.Dispose();
}, null, (int)timeout.TotalMilliseconds, Timeout.Infinite);
request.BeginGetResponse(r =>
{
var httpRequest = (HttpWebRequest)r.AsyncState;
var httpResponse = (HttpWebResponse)httpRequest.EndGetResponse(r);
using (var reader = new StreamReader(httpResponse.GetResponseStream()))
{
var response = reader.ReadToEnd();
tcs.TrySetResult(response);
}
});
return tcs.Task;
}
Комментарии:
1. еще один отличный ответ от Клауса. Превосходит мой комментарий / ответ. Спасибо! TPL довольно потрясающий. не думал об этом.
2. Клаус, это лучшее решение? Я использовал первый ответ в этой теме и добавил NotifyComplete в часть кода для тайм-аута, а также добавил NotifyComplete, где устанавливается плитка. Таким образом, NotifyComplete следует вызывать независимо от того, истек ли тайм-аут httpwebrequest или нет? Всю ночь мой телефон работал в режиме flightmode, и сегодня утром живая плитка снова начала обновляться.
3. Ответ Клауса в основном лучше, потому что он использует существующую инфраструктуру TPL для достижения того же, что и я, но с гораздо меньшим количеством кода и, следовательно, менее подвержен ошибкам. Но моя реализация работает так же хорошо, как и его.
4. Хорошо, круто! Спасибо вам обоим! Так замечательно получить помощь, когда вы застряли.
5. Ну, это другое решение. Я думаю, что invalidusername также предоставил хорошее решение. Мне просто было скучно на работе, когда я писал это 😉