0

this is not a question on how to abort thread pointhunters.

i am making a multi-threaded program which has a httpwebrequest in each one of the running threads and I figured that if I want to stop all of them what they are doing midway thru I must time them out. is there a way to do that on a multi-threaded basis? each thread looks like this:

        HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
        webRequest.Method = "GET";
        webRequest.Accept = "text/html";
        webRequest.AllowAutoRedirect = false;
        webRequest.Timeout = 1000 * 10;
        webRequest.ServicePoint.Expect100Continue = false;
        webRequest.ServicePoint.ConnectionLimit = 100;
        webRequest.UserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.152 Safari/537.36";
        webRequest.Proxy = null;
        WebResponse resp;
        string htmlCode = null;

        try
        {
           resp = webRequest.GetResponse();
           StreamReader sr = new StreamReader(resp.GetResponseStream(), System.Text.Encoding.UTF8);
           htmlCode = sr.ReadToEnd();
           sr.Close();
           resp.Close();
         }
    catch (Exception)
tim_po
  • 105
  • 10

1 Answers1

0

Timing out events explicitly is not a good method. You may want to look into Cancel Async Tasks after a Period of Time.

You can cancel an asynchronous operation after a period of time by using the CancellationTokenSource.CancelAfter method if you don't want to wait for the operation to finish. This method schedules the cancellation of any associated tasks that aren’t complete within the period of time that’s designated by the CancelAfter expression.

Sample code from MSDN :

// Declare a System.Threading.CancellationTokenSource.
        CancellationTokenSource cts;

        private async void startButton_Click(object sender, RoutedEventArgs e)
        {
            // Instantiate the CancellationTokenSource.
            cts = new CancellationTokenSource();    
            resultsTextBox.Clear();    
            try
            {
                // ***Set up the CancellationTokenSource to cancel after 2.5 seconds. (You 
                // can adjust the time.)
                cts.CancelAfter(2500);    
                await AccessTheWebAsync(cts.Token);
                resultsTextBox.Text += "\r\nDownloads succeeded.\r\n";
            }
            catch (OperationCanceledException)
            {
                resultsTextBox.Text += "\r\nDownloads canceled.\r\n";
            }
            catch (Exception)
            {
                resultsTextBox.Text += "\r\nDownloads failed.\r\n";
            }    
            cts = null; 
        }    

        // You can still include a Cancel button if you want to. 
        private void cancelButton_Click(object sender, RoutedEventArgs e)
        {
            if (cts != null)
            {
                cts.Cancel();
            }
        }    

        async Task AccessTheWebAsync(CancellationToken ct)
        {
            // Declare an HttpClient object.
            HttpClient client = new HttpClient();    
            // Make a list of web addresses.
            List<string> urlList = SetUpURLList();    
            foreach (var url in urlList)
            {
                // GetAsync returns a Task<HttpResponseMessage>.  
                // Argument ct carries the message if the Cancel button is chosen.  
                // Note that the Cancel button cancels all remaining downloads.
                HttpResponseMessage response = await client.GetAsync(url, ct);    
                // Retrieve the website contents from the HttpResponseMessage. 
                byte[] urlContents = await response.Content.ReadAsByteArrayAsync();    
                resultsTextBox.Text +=
                    String.Format("\r\nLength of the downloaded string: {0}.\r\n"
                   , urlContents.Length);
            }
        }

There is also Thread.Abort Method which terminates the thread.

EDIT : Canceling the Task - A better Explanation (source)

The Task class provides a way to cancel the started task based on the CancellationTokenSource class.

Steps to cancel a task:

  1. The asynchronous method should except a parameter of type CancellationToken

  2. Create an instance of CancellationTokenSource class like: var cts = new CancellationTokenSource();

  3. Pass the CancellationToken from the instace to the asynchronous method, like: Task<string> t1 = GreetingAsync("Bulbul", cts.Token);

  4. From the long running method, we have to call ThrowIfCancellationRequested() method of CancellationToken.

              static string Greeting(string name, CancellationToken token)
                {
                   Thread.Sleep(3000);
                   token. ThrowIfCancellationRequested();
                  return string.Format("Hello, {0}", name);
                }
    
  5. Catch the OperationCanceledException from where we are awiting for the Task.

  6. We can cancel the operation by calling Cancel method of instance of CancellationTokenSource, OperationCanceledException will be thrown from the long running operation. We can set time to cancel the operation to the instanc also.

Further Details - MSDN Link.

    static void Main(string[] args)
    {
        CallWithAsync();
        Console.ReadKey();           
    }

    async static void CallWithAsync()
    {
        try
        {
            CancellationTokenSource source = new CancellationTokenSource();
            source.CancelAfter(TimeSpan.FromSeconds(1));
            var t1 = await GreetingAsync("Bulbul", source.Token);
        }
        catch (OperationCanceledException ex)
        {
            Console.WriteLine(ex.Message);
        }
    }

    static Task<string> GreetingAsync(string name, CancellationToken token)
    {
        return Task.Run<string>(() =>
        {
            return Greeting(name, token);
        });
    }

    static string Greeting(string name, CancellationToken token)
    {
        Thread.Sleep(3000);
        token.ThrowIfCancellationRequested();
        return string.Format("Hello, {0}", name);
    }
Rohit Vipin Mathews
  • 11,629
  • 15
  • 57
  • 112
  • but i can simply set a timeout to my httpwebrequest. is there a way i can access the object im creating? i have a threadlist of all the threads. – tim_po Jun 01 '15 at 15:12
  • You are trying to `Timeout` the `HttpWebRequest` which is being executed on your thread. I dont think that would be possible or even if it is. That is not the right way. – Rohit Vipin Mathews Jun 02 '15 at 05:22
  • @tim_po - Please see the Edit, I have added explanation of usage of `CancellationToken` – Rohit Vipin Mathews Jun 02 '15 at 07:01