C# .NET - Thread Pool - Thread Stop?? - Asked By Hamit YILDIRIM on 01-Oct-08 06:14 PM

Hello,
I am trying to send asynchronous web request and scrape the html content from the particular web page. I am using thread pool for easiest management of threading. Everything is working fine. There are 2 buttons. One for starting scraping and another for stop the process. How can i code stop button? I want to stop the process running whenever anyone press stop. Here is my code:

'Code begins
  Private Sub ScanTimeoutCallback(ByVal State As Object, ByVal timedOut As Boolean)
        If timedOut Then
            Dim reqState As RequestState = CType(State, RequestState)
            Dim HTTPData As DataObject
            Dim sites As String = ""
            If Not reqState Is Nothing Then
                HTTPData = reqState.HTTPDataObj
                reqState.RequestObj.Abort()
                sites = reqState.sites
            End If
        End If
    End Sub
'This is the thread pooling sub. I just call it like this - sendrequest(arrlist)
    Public Sub SendRequest(ByVal uri As ArrayList)
        For Each siteurl As String In uri
            Dim httpdata As DataObject
            httpdata = New DataObject
            Dim Request As Net.HttpWebRequest = Net.HttpWebRequest.Create(siteurl)
            Request.KeepAlive = True
            Request.Method = "GET"
            'ThreadPool.SetMaxThreads(1, 1)
            '-- Asynchronously send the request
            Dim State As New RequestState(httpdata, Request, siteurl)
            Dim Result As IAsyncResult = CType(Request.BeginGetResponse(New AsyncCallback(AddressOf ReceiveResult), State), IAsyncResult)
            ThreadPool.RegisterWaitForSingleObject(Result.AsyncWaitHandle, New WaitOrTimerCallback(AddressOf ScanTimeoutCallback), State, 18000000, True)
        Next
    End Sub

    Private Sub ReceiveResult(ByVal Result As IAsyncResult)
        '-- Asynchronously receive the response
        Dim State As RequestState = CType(Result.AsyncState, RequestState)
        Dim SR As IO.StreamReader
        Dim Response As Net.HttpWebResponse
        Dim Request As Net.HttpWebRequest = State.RequestObj
        Try

            Response = CType(Request.EndGetResponse(Result), Net.HttpWebResponse)
            SR = New IO.StreamReader(Response.GetResponseStream()) '###
            datastring = SR.ReadToEnd
            datastring = extractemail(datastring)
            dataurl = Request.Address.ToString
            accesscontrol()
        Catch WebEx As Net.WebException
            datastring = "error occured"
            dataurl = Request.Address.ToString
            accesscontrol()
        Finally
            If Not Response Is Nothing Then
                Response.Close()
            End If
            If Not SR Is Nothing Then
                SR.Close()
            End If
        End Try
    End Sub
    Sub accesscontrol()
        If Me.InvokeRequired Then
            Me.Invoke(New MethodInvoker(AddressOf accesscontrol))
        Else
'do something
End Sub

'Code ended

The whole process is working perfectly well. But how can i manage stop the process. I got the thread pooling code from the bromberg's article in eggheadcafe.com in c#. I just want to ask some guru whether my code is right or not. I want to make it more faster.

Regards...

the code in the C# - Hamit YILDIRIM replied to Hamit YILDIRIM on 01-Oct-08 06:21 PM

 
    private void ScanTimeoutCallback(object State, bool timedOut) {
        
if (timedOut) {
            RequestState reqState 
((RequestState)(State));
            
DataObject HTTPData;
            string 
sites "";
            if 
(!(reqState == null)) {
                HTTPData 
reqState.HTTPDataObj;
                
reqState.RequestObj.Abort();
                
sites reqState.sites;
            
}
        }
    }
    
    
// This is the thread pooling sub. I just call it like this - sendrequest(arrlist)
    
public void SendRequest(ArrayList uri) {
        
foreach (string siteurl in uri) {
            DataObject httpdata
;
            
httpdata = new DataObject();
            
Net.HttpWebRequest Request Net.HttpWebRequest.Create(siteurl);
            
Request.KeepAlive = true;
            
Request.Method "GET";
            
RequestState State = new RequestState(httpdata, Request, siteurl);
            
IAsyncResult Result ((IAsyncResult)(Request.BeginGetResponse(new AsyncCallback(new System.EventHandler(this.ReceiveResult)), State)));
            
ThreadPool.RegisterWaitForSingleObject(Result.AsyncWaitHandle, new WaitOrTimerCallback(new System.EventHandler(this.ScanTimeoutCallback)), State, 18000000true);
        
}
    }
    
    
private void ReceiveResult(IAsyncResult Result) {
        
// -- Asynchronously receive the response
        
RequestState State ((RequestState)(Result.AsyncState));
        
IO.StreamReader SR;
        
Net.HttpWebResponse Response;
        
Net.HttpWebRequest Request State.RequestObj;
        try 
{
            Response 
((Net.HttpWebResponse)(Request.EndGetResponse(Result)));
            
SR = new IO.StreamReader(Response.GetResponseStream());
            
// ###
            
datastring SR.ReadToEnd;
            
datastring extractemail(datastring);
            
dataurl Request.Address.ToString;
            
accesscontrol();
        
}
        
catch (Net.WebException WebEx) {
            datastring 
"error occured";
            
dataurl Request.Address.ToString;
            
accesscontrol();
        
}
        
finally {
            
if (!(Response == null)) {
                Response.Close()
;
            
}
            
if (!(SR == null)) {
                SR.Close()
;
            
}
        }
    }
    
    
void accesscontrol() {
        
if (this.InvokeRequired) {
            
this.Invoke(new MethodInvoker(new System.EventHandler(this.accesscontrol)));
        
}
        
else {
            
// do something
        
}
    }

re - Web Star replied to Hamit YILDIRIM on 03-Oct-08 05:33 AM

Is there any way for the Service.OnStop() method to know which threads in the threadpool are running processes started by the main thread and is there any way to graciously stop those threads so that the system remains in a clean state when the service is stopped?

Solution:

1.

I’m not sure if this is the correct way, but the way I do it is the following:

Create a bool that your worker threads check to determine whether they should return immediately (e.g. public bool Shutdown_Now = false). Then in your OnStop() do: Shutdown_Now=true; Now you might want to assume that your threads have quit, but in the event that they haven’t, your service will fail to stop (which is probably a bug). Generally to prevent this from ever occurring, I’ll store a reference to Thread.CurrentThread whenever a worker thread starts. Then when OnStop() is called, I’ll notify them to quit with the Shutdown_Now bool and wait to see if the threads are still running after N seconds. If they are, then I’ll call thread.Abort().

So long as you keep track of all the worker threads being used and make sure you dereference the threads that have completed, you shouldn’t have a problem

2.

What I have done and don't know if this is the best way is to create a ManualResetEvent and pass it to my worker threads. My worker threads will keep checking this and if it gets signaled they will shutdown. My OnStop() method simply signals the ManualResetEvent. I also create ManualResetEvents that my worker threads signal when they finish and I can also listen for those after I ask them to shutdown.

3.

We had a similar problem. Have some global object that all threads can access. In your OnStop set that signal variable so that all threads would know that on stop is signaled. You will have to implement a logic in each thread function to check the stop signal variable and wind up processing immediately. Also once you set the variable in OnStop, put a sleep for 10-15 seconds (based on how much is your winding logic for each thread).

 

All these solution are pretty similar in the sense the onus (and logic) was on the worker thread to keep checking at regular interval if it has to stop processing. which i don't like doing. this makes me wish there was a way i could signal to a worker thread to exit as fast as it can but this is not supported as of now :

Second - Hamit YILDIRIM replied to Web Star on 04-Oct-08 02:20 PM

ok I think second manner is the best.

Thanks..