C# 如何使用队列和睡眠组织多线程
为什么我真的需要这个:(底部的问题简单描述,在edit3下) 让我们想象一下,我试图为twitter创建应用程序。它的帐户数和我现在或以后添加的帐户数一样多(例如10个)。因此,对于每个客户,我们都有一个选择:C# 如何使用队列和睡眠组织多线程,c#,winforms,twitter,C#,Winforms,Twitter,为什么我真的需要这个:(底部的问题简单描述,在edit3下) 让我们想象一下,我试图为twitter创建应用程序。它的帐户数和我现在或以后添加的帐户数一样多(例如10个)。因此,对于每个客户,我们都有一个选择: 来自rss的twite 跟随人们 再给我一根树枝 当我们谈论一个帐户时,每个任务都应该在后台工作,并在其他帐户内同步。对于其中一个帐户,一次不会有twite和跟踪(太多请求) 好的,这意味着,我必须在一个时间内每个帐户只做一个任务。这是否意味着,我必须为这个时刻帐户中的每个活动组织一个线
Parallel.ForEach(readyToExec, new ParallelOptions { MaxDegreeOfParallelism = 5 }, eq =>
{
lock (eq)
{
QueueElement exec_elem = eq.elements[0];
Console.WriteLine(exec_elem.timeToExecute + ": " + eq.account.Name + " " + exec_elem.EventType);
exec_elem.timeToExecute = DateTime.Now + exec_elem.timeDelay;
eq.timeLastExecute = DateTime.Now;
eq.elements.Sort();
eq.isactive = false;
}
});
顺便说一下,在添加要执行的事件之前添加了检查:
foreach (var equeue in queue)
{
if (!equeue.isactive && equeue.elements[0].readyToExecute)
{
if (DateTime.Now > equeue.timeLastExecute + TimeSpan.FromSeconds(5))
{
equeue.isactive = true;
readyToExec.Add(equeue);
}
else
{
equeue.elements[0].timeToExecute = DateTime.Now + TimeSpan.FromSeconds(5);
}
}
}
要手动延迟执行一个帐户的事件(例如,如果在00:00:00中写入“Hello”,则在00:00:05之前无法开始执行下一个事件,即使执行时间为00:00:02)
所以,它对我来说非常有效;)我的第一个倾向是使用优先级队列和优先级队列。下面是我的做法 首先,创建一个全局
秒表
,以维护应用程序时间。您不希望夏令时或其他时间更改打乱您的计时,因为这可能会导致您在事件之间等待太长时间或使事件发生得太快。因此,您可以:
static Stopwatch ApplicationTime = Stopwatch.StartNew();
class Account
{
// information about the account goes here
public TimeSpan LastEventTime { get; set; }
}
class AccountEvent
{
public Account acct { get; private set; }
public TimeSpan dueTime { get; set; }
public ActionType action { get; private set; } // follow, re-tweet, etc.
// constructor, etc.
}
PriorityQueue<TimeSpan, AccountEvent> EventQueue = new Priority<TimeSpan, AccountEvent>();
var ev = new AccountEvent(userAccount, ApplicationTime.Elapsed.AddMinutes(30), ActionType.Follow);
EventQueue.Enqueue(ev.dueTime, ev);
Timer eventTimer = new System.Threading.Timer(QueueProc, null, TimeSpan.FromSeconds(5), TimeSpan.FromMilliseconds(-1));
void QueueProc(object state)
{
while (eventQueue.Count > 0 && eventQueue.Peek().dueTime < ApplicationTime.Elapsed)
{
AccountEvent ev = eventQueue.Dequeue();
// process item. See comments below.
}
// reset the timer so that it will fire in five seconds
eventTimer.Change(TimeSpan.FromSeconds(5), TimeSpan.FromMilliseconds(-1));
}