Question

So, I'm creating a download manager, and I've designed every bit specifically so that it can be shut down at any second without giving it the time to clean up. However, I can't seem to find a way to kill my downloader threads. I tried using Thread.Abort (actually, that's my way of giving them time to clean up: they catch the ThreadAbortException and handle it themselves), but as you can already guess, it's no good. I'd use a flag or something, but when a thread is waiting for a network operation to complete, it's pretty much blocked completely. Any ideas on how to at least interrupt the network operation so I can shut down without waiting a noticeable amount of time?

Here's the relevant piece of code:

try
{
    Request.AddRange(StartPosition, EndPosition);
    Owner.SetDefaultRequestParameters(Request);

    Response = Request.GetResponse() as HttpWebResponse;
    ResponseStream = Response.GetResponseStream();

    var Buffer = new Byte[Downloader.BUFFER_SIZE];

    while (true)
    {
        Paused.Wait();

        if (bStopRequested)
            break;

        int Count = ResponseStream.Read(Buffer, 0, Buffer.Length); //gets stuck here
        if (Count == 0)
            break;

        MemoryStream.Write(Buffer, 0, Count);
        Downloaded += Count;
        CurrentStreak += Count;

        if (StartPosition + Downloaded >= EndPosition)
            break;

        if (MemoryStream.Capacity - CurrentStreak < Buffer.Length)
        {
            Owner.WriteToFile(MemoryStream, StartPosition + Downloaded - CurrentStreak, CurrentStreak);
            MemoryStream.Seek(0, SeekOrigin.Begin);
            CurrentStreak = 0;
        }
    }
}
catch (ThreadAbortException)
{
    try
    {
        Response.Close();
    }
    catch { }

    return; //fastest way I have found to shut the thread down, yet
}

EDIT: So, here's how I did it:

if (Request != null)
    Request.Abort();
if (Response != null)
    Response.Close();
ExecutionThread.Abort();

With this, no matter where the thread is stuck (getting a response or reading from the response stream) it will get cancelled and stop immediately.

Was it helpful?

Solution

You could Dispose the ResponseStream and then catch an ObjectDisposedException.

While this may work i suggest you design your application using CancellationToken to allow it to gracefully close instead of abruptedly aborting threads. You also might consider using async-await to make your application more scalable and non-blocking.

OTHER TIPS

Not sure what the underlying socket does but if all fails you can directly bind to a socket in non blocking mode und use the Socket.BeginReceive method which will call your call back when data has arrived. If you do want to cancel the current operation you can call close simply the socket and thats it. See MSDN

The asynchronous BeginReceive operation must be completed by calling the EndReceive method. Typically, the method is invoked by the callback delegate.

This method does not block until the operation is complete. To block until the operation is complete, use one of the Receive method overloads.

To cancel a pending BeginReceive, call the Close method.

You should check if you can get your hands on the underlying socket and try to close it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top