[英]Killing HttpWebRequest object using Thread.Abort
所有,我試圖使用類似於下面的代碼的方法取消兩個並發的HttpWebRequests(以偽ish C#顯示)。
Main方法創建兩個創建HttpWebRequests的線程。 如果用戶希望,他們可以通過單擊按鈕然后調用Abort方法來中止請求。
private Thread first;
private Thread second;
private string uri = "http://somewhere";
public void Main()
{
first = new Thread(GetFirst);
first.Start();
second = new Thread(GetSecond);
second.Start();
// Some block on threads... like the Countdown class
countdown.Wait();
}
public void Abort()
{
try
{
first.Abort();
}
catch { // do nothing }
try
{
second.Abort();
}
catch { // do nothing }
}
private void GetFirst(object state)
{
MyHandler h = new MyHandler(uri);
h.RunRequest();
}
private void GetSecond(object state)
{
MyHandler h = new MyHandler(uri);
h.RunRequest();
}
第一個線程被SocketException中斷:
A blocking operation was interrupted by a call to WSACancelBlockingCall
第二個線程掛起在GetResponse()上。
如何以Web服務器知道連接已中止的方式中止這兩個請求? ,和/或, 有更好的方法嗎?
UPDATE
正如所建議的,一個很好的選擇是使用BeginGetResponse。 但是,我無法訪問HttpWebRequest對象 - 它在MyHandler
類中被抽象化。 我已經修改了這個問題來證明這一點。
public class MyHandler
{
public void RunRequest(string uri)
{
HttpWebRequest req = HttpWebRequest.Create(uri);
HttpWebResponse res = req.GetResponse();
}
}
使用BeginGetResponse
啟動調用,然后使用類上的Abort
方法取消它。
http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest_methods.aspx
我相信Abort
不能使用同步GetResponse
:
http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.abort.aspx
如果你必須堅持同步版本,要殺死這種情況,你所能做的只是中止線程。 要放棄等待,您可以指定超時:
http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.timeout.aspx
如果你需要殺死進程,我會爭辯在新的AppDomain中啟動它並在你想殺死請求時刪除AppDomain; 而不是在主進程中中止一個線程。
ThreadAbortException是高度非特定的。 HttpWebRequest已經支持一種使用Abort()方法以可預測的方式取消請求的方法。 我建議你改用它。
請注意,您仍將在該線程上獲得WebException,旨在告訴您該請求已在外部中止。 准備抓住它。
這可能是因為.NET的連接池。 每個WebRequest實例都有一個ServicePoint,用於描述您要與之通信的目標(服務器地址,端口,協議......)。 這些ServicePoints將被重用,因此如果您創建具有相同服務器地址,端口和協議的2個WebRequests,它們將共享相同的ServicePoint實例。
當您調用WebRequest.GetResponse()時,它使用ServicePoint提供的連接池來創建連接。 如果您隨后使用Thread.Abort()終止該線程,它將不會返回與ServicePoint的連接池的連接,因此ServicePoint認為此連接仍在使用中。 如果達到ServicePoint的連接限制(默認值:2),它將不會創建任何新連接,而是等待返回其中一個打開的連接。
您可以像這樣增加連接限制:
HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(url);
httpRequest.ServicePoint.ConnectionLimit = 10;
或者您可以使用默認連接限制,因此每個新ServicePoint都將使用此限制:
System.Net.ServicePointManager.DefaultConnectionLimit = 10;
您還可以使用ServicePoint.CurrentConnections來獲取打開的連接數。
您可以使用以下方法中止您的線程:
private Thread thread;
private Uri uri;
void StartThread()
{
thread = new Thread(new ThreadStart(() =>
{
WebRequest request = WebRequest.Create(uri);
request.ConnectionGroupName = "SomeConnectionGroup";
var response = request.GetResponse();
//...
}));
thread.Start();
}
void AbortThread()
{
thread.Abort();
ServicePointManager.FindServicePoint(uri).CloseConnectionGroup("SomeConnectionGroup");
}
請記住,將終止與具有相同連接組名稱的同一服務器(或ServicePoint)的所有連接。 如果您有多個並發線程,則可能需要為它們分配唯一的連接組名稱。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.