У меня есть это базовое консольное приложение на C #, которое асинхронно использует WebRequest для получения html из списка сайтов.Он работает нормально, но как мне настроить триггер, который срабатывает при обработке каждого сайта в списке?
Я потратил пару часов на изучение различных решений в Интернете, включая документы MS, но ни одногоиз них дать прямой ответ через код.Я читал о IAsyncResult.AsyncWaitHandle, но не знаю, как интегрировать его в мой код.Я просто хотел бы вызвать пользовательскую функцию, когда все потоки завершают обработку или время ожидания.
Одна хитрость в том, что я никогда не знаю заранее, сколько сайтов в моем списке (это определяется пользователем), поэтому мне нужнорешение, достаточно надежное, чтобы ждать 5 событий для завершения 100 000 событий.
Спасибо.Рабочий код ниже:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using System.Threading;
namespace AsyncApp_01
{
class Program
{
static void Main(string[] args)
{
ArrayList alSites = new ArrayList();
alSites.Add("http://www.google.com");
alSites.Add("http://www.lostspires.com");
ScanSites(alSites);
Console.Read();
}
private static void ScanSites(ArrayList sites)
{
foreach (string uriString in sites)
{
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, (30 * 1000), true);
}
}
private static void UpdateItem(IAsyncResult result)
{
// 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);
}
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;
}
}
}
}
Бонусные баллы для всех, кто также может подсказать мне, как ограничить количество одновременных потоков.Например, если у меня есть 100 сайтов для обработки, как мне настроить так, чтобы 10 сайтов обрабатывались одновременно, но не больше.Я не хочу открывать 100 тем.