同时下载限制

发布于 2024-12-03 11:45:06 字数 3472 浏览 0 评论 0原文

我正在使用 WebRequest.BeginGetResponse 从服务器下载文件。一切都很好,但我不想同时下载 5 个文件。在 Java 中,我会使用固定线程池,但我不知道如何在 C# 中执行相同的操作。有什么想法吗?

class HttpFetcher
{
    public void MakeRequest(Uri uri)
    {
        WebRequest request = WebRequest.Create(uri);
        request.Proxy = null;
        RequestState requestState = new RequestState();
        requestState.Request = request;
        IAsyncResult result = (IAsyncResult) request.BeginGetResponse(new AsyncCallback(ResponseCallback), requestState);

        ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle, new WaitOrTimerCallback(TimeOutCallback), request, 1000, true);
    }

    private void ResponseCallback(IAsyncResult result)
    {
        try
        {
            RequestState requestState = (RequestState)result.AsyncState;
            WebRequest request = requestState.Request;
            requestState.Response = request.EndGetResponse(result);
            Stream responseStream = requestState.Response.GetResponseStream();
            requestState.ResponseStream = responseStream;
            IAsyncResult asynchronousResultRead = responseStream.BeginRead(requestState.BufferRead, 0, 1024, new AsyncCallback(ReadCallback), requestState);
        }
        catch (Exception ex)
        {
            Console.WriteLine("Exception raised!");
            Console.WriteLine("Message : {0}", ex.Message);
            RequestState state = (RequestState)result.AsyncState;
            if (state.Response != null)
                state.Response.Close();
        }

    }

    private void ReadCallback(IAsyncResult result)
    {
        try
        {
            RequestState requestState = (RequestState)result.AsyncState;
            Stream responseStream = requestState.ResponseStream;

            int bytesRead = responseStream.EndRead(result);
            if (bytesRead > 0)
            {
                requestState.RequestData.Append(Encoding.ASCII.GetString(requestState.BufferRead, 0, bytesRead));
                IAsyncResult asynchronousResult = responseStream.BeginRead(requestState.BufferRead, 0, 1024, new AsyncCallback(ReadCallback), requestState);
            }
            else
            {
                Console.WriteLine("\nThe HTML page Contents are:  ");
                if (requestState.RequestData.Length > 1)
                {
                    string sringContent;
                    sringContent = requestState.RequestData.ToString();
                    //Console.WriteLine(sringContent);
                }
                Console.WriteLine("\nPress 'Enter' key to continue........");
                responseStream.Close();
            }
        }
        catch (WebException e)
        {
            Console.WriteLine("WebException raised!");
            Console.WriteLine("\n{0}", e.Message);
            Console.WriteLine("\n{0}", e.Status);
        }
        catch (Exception e)
        {
            Console.WriteLine("Exception raised!");
            Console.WriteLine("Source : {0}", e.Source);
            Console.WriteLine("Message : {0}", e.Message);
        }
    }

    private void TimeOutCallback(object state, bool timedOut)
    {
        if (timedOut)
        {
            WebRequest request = (WebRequest)state;
            if (state != null)
            {
                request.Abort();
            }
        }
    }
}

I'm making asynchronous requests with WebRequest.BeginGetResponse to download files from a server. All works nice but I want to download no more of 5 files at the same time. In Java I would use a fixed thread pool but I don't know how to do the same in C#. Any ideas?

class HttpFetcher
{
    public void MakeRequest(Uri uri)
    {
        WebRequest request = WebRequest.Create(uri);
        request.Proxy = null;
        RequestState requestState = new RequestState();
        requestState.Request = request;
        IAsyncResult result = (IAsyncResult) request.BeginGetResponse(new AsyncCallback(ResponseCallback), requestState);

        ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle, new WaitOrTimerCallback(TimeOutCallback), request, 1000, true);
    }

    private void ResponseCallback(IAsyncResult result)
    {
        try
        {
            RequestState requestState = (RequestState)result.AsyncState;
            WebRequest request = requestState.Request;
            requestState.Response = request.EndGetResponse(result);
            Stream responseStream = requestState.Response.GetResponseStream();
            requestState.ResponseStream = responseStream;
            IAsyncResult asynchronousResultRead = responseStream.BeginRead(requestState.BufferRead, 0, 1024, new AsyncCallback(ReadCallback), requestState);
        }
        catch (Exception ex)
        {
            Console.WriteLine("Exception raised!");
            Console.WriteLine("Message : {0}", ex.Message);
            RequestState state = (RequestState)result.AsyncState;
            if (state.Response != null)
                state.Response.Close();
        }

    }

    private void ReadCallback(IAsyncResult result)
    {
        try
        {
            RequestState requestState = (RequestState)result.AsyncState;
            Stream responseStream = requestState.ResponseStream;

            int bytesRead = responseStream.EndRead(result);
            if (bytesRead > 0)
            {
                requestState.RequestData.Append(Encoding.ASCII.GetString(requestState.BufferRead, 0, bytesRead));
                IAsyncResult asynchronousResult = responseStream.BeginRead(requestState.BufferRead, 0, 1024, new AsyncCallback(ReadCallback), requestState);
            }
            else
            {
                Console.WriteLine("\nThe HTML page Contents are:  ");
                if (requestState.RequestData.Length > 1)
                {
                    string sringContent;
                    sringContent = requestState.RequestData.ToString();
                    //Console.WriteLine(sringContent);
                }
                Console.WriteLine("\nPress 'Enter' key to continue........");
                responseStream.Close();
            }
        }
        catch (WebException e)
        {
            Console.WriteLine("WebException raised!");
            Console.WriteLine("\n{0}", e.Message);
            Console.WriteLine("\n{0}", e.Status);
        }
        catch (Exception e)
        {
            Console.WriteLine("Exception raised!");
            Console.WriteLine("Source : {0}", e.Source);
            Console.WriteLine("Message : {0}", e.Message);
        }
    }

    private void TimeOutCallback(object state, bool timedOut)
    {
        if (timedOut)
        {
            WebRequest request = (WebRequest)state;
            if (state != null)
            {
                request.Abort();
            }
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

苍风燃霜 2024-12-10 11:45:06

您可以使用 Task.Factory.FromAsync() 并使用任务计划程序来限制并发

无需深入探讨 FromAsync(),这里是一个非常简化的示例,显示最多 5 个任务并行运行,无论有多少个任务排队:

public static void Main()
{
    var scheduler = new LimitedConcurrencyLevelTaskScheduler(5);
    TaskFactory factory = new TaskFactory(scheduler);

    for (int i = 0; i < 50; i++)
    {
        int idx = i;
        var newTask = factory.StartNew(() =>
            {
                Console.WriteLine("Starting " + idx);
                Thread.Sleep(5000);
            });
    }
    Console.ReadLine();
}

You could use Task.Factory.FromAsync() and use a Task Scheduler that limits the Degree of Concurrency

Without diving into FromAsync() here a very simplified example that shows that at most 5 tasks are running in parallel, regardless how many are queued:

public static void Main()
{
    var scheduler = new LimitedConcurrencyLevelTaskScheduler(5);
    TaskFactory factory = new TaskFactory(scheduler);

    for (int i = 0; i < 50; i++)
    {
        int idx = i;
        var newTask = factory.StartNew(() =>
            {
                Console.WriteLine("Starting " + idx);
                Thread.Sleep(5000);
            });
    }
    Console.ReadLine();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文