Killing HttpWebRequest object using Thread.Abort

后端 未结 3 1753
-上瘾入骨i
-上瘾入骨i 2020-12-19 09:20

All, I am trying to cancel two concurrent HttpWebRequests using a method similar to the code below (shown in pseudo-ish C#).

The Main method creates two threads whic

相关标签:
3条回答
  • 2020-12-19 09:54

    A ThreadAbortException is highly non-specific. HttpWebRequest already supports a way to cancel the request in a predictable way with the Abort() method. I recommend you use it instead.

    Note that you'll still get a WebException on the thread, designed to tell you that the request got aborted externally. Be prepared to catch it.

    0 讨论(0)
  • 2020-12-19 09:55

    This might be because of .NET's connection pooling. Every WebRequest-instance has a ServicePoint that describes the target you want to communicate with (server address, port, protocol,...). These ServicePoints will be reused, so if you create 2 WebRequests with the same server address, port and protocol they will share the same ServicePoint instance.

    When you call WebRequest.GetResponse() it uses the connection pool provided by the ServicePoint to create connections. If you then kill the thread with Thread.Abort() it will NOT return the connection to the ServicePoint's connection pool, so the ServicePoint thinks this connection is still in use. If the connection limit of the ServicePoint is reached (default: 2) it will not create any new connections, but instead wait for one of the open connections to be returned.

    You can increase the connection limit like this:

    HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(url);
    httpRequest.ServicePoint.ConnectionLimit = 10;
    

    or you can use the default connection limit, so every new ServicePoint will use this limit:

    System.Net.ServicePointManager.DefaultConnectionLimit = 10;
    

    You can also use ServicePoint.CurrentConnections to get the number of open connections.

    You could use the following method to abort your thread:

        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");
        }
    

    Remember that ALL connections to the same server (or ServicePoint) that have the same connection group name will be killed. If you have multiple concurrent threads you might want to assign unique connection group names to them.

    0 讨论(0)
  • 2020-12-19 10:15

    Use BeginGetResponse to initiate the call and then use the Abort method on the class to cancel it.

    http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest_methods.aspx

    I believe Abort will not work with the synchronous GetResponse:

    http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.abort.aspx

    If you have to stick with the synchronous version, to kill the situation, all you can do is abort the thread. To give up waiting, you can specify a timeout:

    http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.timeout.aspx

    If you need to kill the process, I would argue launching it inside a new AppDomain and dropping the AppDomain when you want to kill the request; instead of aborting a thread inside your main process.

    0 讨论(0)
提交回复
热议问题