我有这个小C#控制台程序,它设计用于运行URL列表并从相应页面获取html。它在某种程度上起作用,但是我在使Async callbacks
执行适当的次数并处理超时时遇到问题。
问题:我收到了不稳定的结果。有时我运行代码并且结果是按预期的(例如,我给它看7个URL,它输出7个结果和1个完整事件),但有时候结果对我没有意义(例如,我运行7个URL并获得2或3个完整事件或仅6个结果,完全没有完整事件。有人可以解释为什么会发生这种情况以及如何解决这个问题吗?
即使运行完全相同的7个网址,结果也会有所不同。我想这是因为有时网站超时,但我的代码旨在优雅地处理超时。它还旨在处理不正确的URL。给它几个跑步让我知道你的想法。
这让我疯了!
最终解决方案处理不适当的URL,超时和不存在的站点非常重要。一旦处理完所有网址,就会触发 onComplete 事件。
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
namespace AsyncApp_03
{
using System;
using System.Net;
using System.IO;
using System.Text;
using System.Threading;
class Program
{
static int _count = 0;
static int _invalid = 0;
static int _total = 0;
static void Main(string[] args)
{
ArrayList alSites = new ArrayList();
alSites.Add("http://www.google.com");
alSites.Add("adsfsdfsdfsdffd");
alSites.Add("http://wwww.fjasjfejlajfl");
alSites.Add("http://mundocinema.com/noticias/the-a-team-2/4237");
alSites.Add("http://www.spmb.or.id/?p=64");
alSites.Add("http://gprs-edge.ru/?p=3");
alSites.Add("http://blog.tmu.edu.tw/MT/mt-comments.pl?entry_id=3141");
_total = alSites.Count;
ScanSites(alSites);
Console.Read();
}
private static void ScanSites(ArrayList sites)
{
foreach (string uriString in sites)
{
try
{
WebRequest request = HttpWebRequest.Create(uriString);
request.Method = "GET";
object data = new object(); //container for our "Stuff"
// RequestState is a custom class to pass info to the callback
RequestState state = new RequestState(request, data, uriString);
IAsyncResult result = request.BeginGetResponse(new AsyncCallback(UpdateItem), state);
//Register the timeout callback
ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle, new WaitOrTimerCallback(ScanTimeoutCallback), state, (5 * 1000), true);
}
catch
{
Console.WriteLine("Invalid URL: " + uriString);
_invalid++;
Console.WriteLine("Count: " + (_invalid + _count));
Console.WriteLine("----------------------------------------------");
}
}
}
private static void UpdateItem(IAsyncResult result)
{
try
{
// grab the custom state object
RequestState state = (RequestState)result.AsyncState;
WebRequest request = (WebRequest)state.Request;
// get the Response
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result);
Stream s = (Stream)response.GetResponseStream();
StreamReader readStream = new StreamReader(s);
// dataString will hold the entire contents of the requested page if we need it.
string dataString = readStream.ReadToEnd();
response.Close();
s.Close();
readStream.Close();
//Console.WriteLine(dataString);
Console.WriteLine("Site HTML: " + state.SiteUrl);
}
catch
{
RequestState state = (RequestState)result.AsyncState;
WebRequest request = (WebRequest)state.Request;
Console.WriteLine("Couldn't Resolve URL: " + state.SiteUrl);
}
Interlocked.Increment(ref _count);
Console.WriteLine("Count: " + (_invalid + _count));
Console.WriteLine("----------------------------------------------");
// All URL look-ups complete
if ((_count + _invalid) == _total)
{
Console.WriteLine("Complete!");
}
}
private static void ScanTimeoutCallback(object state, bool timedOut)
{
if (timedOut)
{
RequestState reqState = (RequestState)state;
if (reqState != null)
{
reqState.Request.Abort();
}
Console.WriteLine("aborted- timeout");
}
}
class RequestState
{
public WebRequest Request; // holds the request
public object Data; // store any data in this
public string SiteUrl; // holds the UrlString to match up results (Database lookup, etc).
public RequestState(WebRequest request, object data, string siteUrl)
{
this.Request = request;
this.Data = data;
this.SiteUrl = siteUrl;
}
}
}
}