views:

145

answers:

1

I implemented a System.Web.IHttpAsyncHandler to limit website bandwidth usage for files download. Once defined user bandwidth, I need to send a byte[] every second (or 1000 milliseconds, to be precise). Something like:

public class DownloadHandler : IHttpAsyncHandler
{
    public IAsyncResult BeginProcessRequest(
        HttpContext context, AsyncCallback cb, object extraData)
    {
        // user can download that file?
        DownloadAsync download = new DownloadAsync(...);
        download.StartDownload()
        return download;
    }
}

class DownloadAsync : IAsyncResult
{
    // ...
    public void StartDownload()
    {
        ThreadPool.QueueUserWorkItem(new WaitCallback(startAsyncTask));
    }

    private void startAsyncTask(object state)
    {
        // ...
        while (context.Response.IsClientConnected &&
               offset < data.Arquivo.Tamanho)
        {
            // ... do stuff
            context.Response.OutputStream.Write(buffer, 0, readCount);
            // ... more stuff
            Thread.Sleep(1000 - (int)elapsed.TotalMilliseconds);
        }
    }
}

Once in ThreadPool.QueueUserWorkItem, I lose control over frequency my code is being executed, so it don't take a second to execute, and that difference reflects on download throughput.

So, my questions are:

  1. Can I define ThreadPool.QueueUserWorkItem check interval?
  2. If not, are there another approach to achieve this requirement (bandwidth throttling?)
  3. If not, can I have a pony?

TIA

+1  A: 

You shouldn't hang on to a PoolThread like that. And in general, any Threading solution that uses Sleep() is suspect.

You can use System.Threading.Timer, I'm not sure about the accuracy (roughly ~20ms) but it will not 'wander off'.

The Timer will replace the while loop inside your delegate.

Henk Holterman