Вариант 3 лучший:
Использовать Async IO.
Если ваша обработка запросов не является сложной и тяжелой, ваша программа будет тратить 99% своего времени на ожидание HTTP-запросов.
Это именно то, для чего предназначен Async IO - пусть сетевой стек Windows (или .net framework или что-то еще) беспокоится обо всех ожиданиях и просто использует один поток для отправки и «получения» результатов.
К сожалению, .NET Framework делает правильную боль в заднице. Это проще, если вы просто используете сырые сокеты или Win32 API. Вот (проверено!) Пример использования C # 3 в любом случае:
using System.Net; // need this somewhere
// need to declare an class so we can cast our state object back out
class RequestState {
public WebRequest Request { get; set; }
}
static void Main( string[] args ) {
// stupid cast neccessary to create the request
HttpWebRequest request = WebRequest.Create( "http://www.stackoverflow.com" ) as HttpWebRequest;
request.BeginGetResponse(
/* callback to be invoked when finished */
(asyncResult) => {
// fetch the request object out of the AsyncState
var state = (RequestState)asyncResult.AsyncState;
var webResponse = state.Request.EndGetResponse( asyncResult ) as HttpWebResponse;
// there we go;
Debug.Assert( webResponse.StatusCode == HttpStatusCode.OK );
Console.WriteLine( "Got Response from server:" + webResponse.Server );
},
/* pass the request through to our callback */
new RequestState { Request = request }
);
// blah
Console.WriteLine( "Waiting for response. Press a key to quit" );
Console.ReadKey();
}
EDIT:
В случае .NET «обратный вызов завершения» фактически запускается в потоке ThreadPool, а не в вашем основном потоке, поэтому вам все равно придется блокировать любые общие ресурсы, но это все же избавляет вас от необходимости управлять резьб.