我正在编写一个可以同时运行多个请求的网络抓取程序。但是,有些请求需要连续发生,所以我首先想到的是围绕两个需要同时发生的请求并锁定其他请求。这种方法的问题在于,其他两个请求将相互锁定,但能够并行运行。
例如,我有四页需要网站上的数据:
当程序启动时,我启动三个线程:一个用于page1,一个用于page2和第3页,一个用于page4。第3页的请求必须在第2页请求后直接发生。对page1和page4的请求可以同时发生。
如果我不使用锁定,则可能会在page2和page3的请求之间请求page1或page4并导致问题。如果我对三个线程使用相同的锁,那么对page1的请求可能会阻止对page4的请求。
如何防止第2页和第3页之间发生请求,但允许其他请求同时发生?
答案 0 :(得分:1)
您可以尝试使用信号量来控制对“页面请求”伪资源的访问。可以并发运行的请求只需要一个资源,必须运行的请求只需要所有资源。
如下所示:
private static Semaphore _pool;
private static readonly int kMaxConcurrrentPageRequesters = 4; // or whatever number
// at some appropriate initialization point
_pool = new Semaphore(kMaxConcurrrentPageRequesters,kMaxConcurrrentPageRequesters);
// when a normal request is being made that can run concurrently:
_pool.WaitOne();
perform_page_request();
_pool.Release();
// when an exclusive page request is being made:
// maybe create a Semaphore wrapper that stores the max semaphore count
// so that you can expose a `WaitAll()` method to replace this loop
for (int i = 0; i < kMaxConcurrrentPageRequesters; ++i) {
_pool.WaitOne();
}
perform_exclusive_page_requests();
_pool.Release(kMaxConcurrrentPageRequesters);
答案 1 :(得分:0)
您可以延迟执行线程或让它们等待。例如,
var waitA = false;
var thread1 = new Thread((Action)(() => { while(!waitA) Thread.Sleep(0); /* do work here */ })).Start();
var thread2 = new Thread((Action)(() => { while(!waitA) Thread.Sleep(0); /* do work here */ })).Start();
// prepare data for threads? and start them
waitA = true;