Un service peut être exagéré pour cela.
Vous pouvez créer un objet global au démarrage de votre application et lui demander de créer un thread d'arrière-plan qui exécute la requête toutes les 5 minutes. Prenez la réponse (ou ce que vous traitez de la réponse) et placez-la dans une classe distincte, en créant une nouvelle instance de cette classe avec chaque réponse et utilisez System.Threading.Interlocked.Exchange
pour remplacer une instance statique chaque fois que la réponse est extraite. Lorsque vous voulez regarder la réponse, copiez simplement une référence à l'instance statique vers une référence de pile et vous obtiendrez les données les plus récentes. Gardez à l'esprit, cependant, qu'ASP.NET supprimera votre application chaque fois qu'il n'y aura pas de demandes pendant un certain temps (temps d'inactivité), votre application s'arrêtera et redémarrera, provoquant la destruction de votre objet global et recréé.
Vous pouvez lire ailleurs que vous ne pouvez pas ou ne devez pas faire des tâches d'arrière-plan dans ASP.NET, mais ce n'est pas vrai - il vous suffit de comprendre les implications. J'ai le code semblable à l'exemple suivant travaillant sur un site ASP.NET qui gère plus de 1000 req/s de pointe (sur plusieurs serveurs).
Par exemple, dans Global.asax.cs:
public class BackgroundResult
{
public string Response; // for simplicity, just use a public field for this example--for a real implementation, public fields are probably bad
}
class BackgroundQuery
{
private BackgroundResult _result; // interlocked
private readonly Thread _thread;
public BackgroundQuery()
{
_thread = new Thread(new ThreadStart(BackgroundThread));
_thread.IsBackground = true; // allow the application to shut down without errors even while this thread is still running
_thread.Name = "Background Query Thread";
_thread.Start();
// maybe you want to get the first result here immediately?? Otherwise, the first result may not be available for a bit
}
/// <summary>
/// Gets the latest result. Note that the result could change at any time, so do expect to reference this directly and get the same object back every time--for example, if you write code like: if (LatestResult.IsFoo) { LatestResult.Bar }, the object returned to check IsFoo could be different from the one used to get the Bar property.
/// </summary>
public BackgroundResult LatestResult { get { return _result; } }
private void BackgroundThread()
{
try
{
while (true)
{
try
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("http://example.com/samplepath?query=query");
request.Method = "GET";
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (StreamReader reader = new StreamReader(response.GetResponseStream(), System.Text.Encoding.UTF8))
{
// get what I need here (just the entire contents as a string for this example)
string result = reader.ReadToEnd();
// put it into the results
BackgroundResult backgroundResult = new BackgroundResult { Response = result };
System.Threading.Interlocked.Exchange(ref _result, backgroundResult);
}
}
}
catch (Exception ex)
{
// the request failed--cath here and notify us somehow, but keep looping
System.Diagnostics.Trace.WriteLine("Exception doing background web request:" + ex.ToString());
}
// wait for five minutes before we query again. Note that this is five minutes between the END of one request and the start of another--if you want 5 minutes between the START of each request, this will need to change a little.
System.Threading.Thread.Sleep(5 * 60 * 1000);
}
}
catch (Exception ex)
{
// we need to get notified of this error here somehow by logging it or something...
System.Diagnostics.Trace.WriteLine("Error in BackgroundQuery.BackgroundThread:" + ex.ToString());
}
}
}
private static BackgroundQuery _BackgroundQuerier; // set only during application startup
protected void Application_Start(object sender, EventArgs e)
{
// other initialization here...
_BackgroundQuerier = new BackgroundQuery();
// get the value here (it may or may not be set quite yet at this point)
BackgroundResult result = _BackgroundQuerier.LatestResult;
// other initialization here...
}
Vous pourriez avoir un service Windows en cours d'exécution pour cela, et écrire les données dans un fichier quelque part l'application ASP peut le lire. –
qu'en est-il d'une demande arrivant juste quand le fichier est écrit? aussi, je ne suis pas sûr si c'est le meilleur moyen? –
Puis attendez un peu jusqu'à ce que le fichier soit lisible. –