在ASP.NET中并行执行.NET HttpWebRequests的建议 [英] Recommendations for executing .NET HttpWebRequests in parallel in ASP.NET

查看:82
本文介绍了在ASP.NET中并行执行.NET HttpWebRequests的建议的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个ASP.NET MVC Web应用程序,可以对其他服务器进行REST风格的Web服务调用.我有一个场景,其中我对两个单独的服务进行了两个HttpWebRequest调用.我需要它们都完成才能继续,但是它们的顺序无关紧要.它们每个可能需要1-2秒,我现在正在按顺序运行它们.并行运行它们会减少用户响应时间,但是最好的方法是什么?

I have an ASP.NET MVC web application that makes REST style web service calls to other servers. I have a scenario where I am making two HttpWebRequest calls to two separate services. I need them both to complete to continue, but their order doesn't matter. They may take 1-2 seconds each and I am running them in sequence now. Running them in parallel would decrease the user response time, but what is the best way?

在研究这个问题时,我可以想到几种选择:

In researching this, I can think of several options:

  • 在主线程上执行一个请求,然后为另一个请求启动另一个线程.应该创建新线程还是使用线程池?如果我使用游泳池,如何确定其大小?另外,不确定如何将线程重新连接在一起(例如,使用 ThreadPool.RegisterWaitForSingleObject )?
  • 尝试并利用内置的 IAsyncResult 支持对于一个或两个请求.同样,不确定异步请求在哪个线程上执行,因此不确定如何确定线程池的大小.如何将IAsyncResult重新加入主线程?所有示例都在回调中找到过程信息,但是我可以在主线程中等待并使用
  • Execute one request on the main thread, and spin up a second thread for the other request. Should created new threads or use a thread pool? If I use a pool, how do I size it? Also, not sure how I can join the threads back together (e.g. use ThreadPool.RegisterWaitForSingleObject)?
  • Try and leverage the built-in IAsyncResult support for one or both of the requests. Again, not sure on which threads the async request execute, so not sure how to size the thread pool. How do I join IAsyncResult back into my main thread? All the examples I find process information in the callback, but I can just wait in my main thread and use the IsCompleted property?

我需要找到一个既可以运行又可以大规模执行的解决方案.这就是为什么我担心线程池的大小.我不希望请求阻塞,因为它们正在等待可用线程.

I need to find a solution that will both function, and perform at scale. That is why I am worried about thread pool sizing. I would hate to have requests blocking because they are waiting for available threads.

推荐答案

One of the answers to Multithreading WebRequests, a good and stable approach? : CSharp uses a ManualResetEvent event = new ManualResetEvent(), a reference counter equaling the number of in flight requests and Interlocked.Decrement to control the event.Set(). The main thread then waits by calling event.WaitOne().

但是, WaitHandles-Auto/ManualResetEvent和Mutex 提到"ManualResetEvent"可能比使用各种Monitor方法(例如Wait,Pulse和PulseAll)要慢得多.

However, WaitHandles - Auto/ManualResetEvent and Mutex mentions that ManualResetEvent "can be significantly slower than using the various Monitor methods" like Wait, Pulse and PulseAll.

我最终基于Noah Blumenthal的博客文章编写了代码:

I ended up basing my code off of this Noah Blumenthal blog post: Run generic tasks async (fluent-ly). I did make two changes: implement IDisposable and call .Close() on the ManualResetEvent and switch from using a lock() to Interlocked .Increment() and .Decrement().

public class AsyncQueueManager : IDisposable {
    private readonly ManualResetEvent waitHandle = new ManualResetEvent(true);
    private int count = 0;

    public AsyncQueueManager Queue(Action<object> action) {
        Interlocked.Increment(ref count);
        waitHandle.Reset();
        Action<object> actionWrapper = CreateActionWrapper(action);
        WaitCallback waitCallback = new WaitCallback(actionWrapper);
        ThreadPool.QueueUserWorkItem(waitCallback);
        return this;
    }

    private Action<object> CreateActionWrapper(Action<object> action) {
        Action<object> actionWrapper = (object state) =>
        {
            try {
                action(state);
            } catch (Exception ex) {
                // log
            } finally {
                if (Interlocked.Decrement(ref count) == 0) {
                    waitHandle.Set();
                }
            }
        };
        return actionWrapper;
    }

    public void Wait() {
        waitHandle.WaitOne();
    }
    public void Wait(TimeSpan timeout) {
        waitHandle.WaitOne(timeout);
    }

    public void Dispose() {
        waitHandle.Close();
    }
}

这篇关于在ASP.NET中并行执行.NET HttpWebRequests的建议的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆