【问题标题】:Delaying Method Calls and Using Threads?延迟方法调用和使用线程?
【发布时间】:2015-07-12 08:33:39
【问题描述】:

假设我有这段特定的代码:

/****************************************************************/
/* Generate new wave of enrollees                               */
/****************************************************************/
for (int i = 1; i <= new Random().Next(enrolleesExpectedPerMinuteMin, enrolleesExpectedPerMinuteMax) && enrolleesInCampus < enrolleesExpectedTotal; i++)
{
    Enrollee newEnrollee = new Enrollee("ENRL" + i, i);
    listOfEnrollees.Add(newEnrollee);
    enrolleesInCampus = listOfEnrollees.Count;    
    lblEnrolleesInCampusNum.Text = enrolleesInCampus.ToString();
    newEnrollee.enroll(listOfOffices);
}

请注意,它在 GUI 计时器的 tick 方法上运行。看,我正在生成 Enrollee 对象。他们有一个名为enroll() 的函数,它接受一个参数,这是一个Enrollee 可以访问的所有Office 对象的列表。

每个Office 对象都有一个ServiceLane 对象列表。这些ServiceLane 对象有一个Enrollees 的队列;还有,称为enqueue()dequeue() 的方法。 enqueue() 只接受Enrollee 类型的参数并将其添加到enrolleesInLine 列表中,该列表表示Enrollee 对象在ServiceLane 对象上排队。 dequeue() 方法当然会执行出队,但我需要它在 ServiceLane 所需的特定处理时间后执行出队。

ServiceLanesEnrollee 的去向取决于 Enrollee 的类型和他们需要进入的当前 Office,因此,我构造了这样的 enroll() 方法:

public void enroll(List<Office> offices)
{
    switch (type)
    {
        case EnrolleeType.NEW_STUDENT:
            // code goes here
            // i.e. :
            // lineInOfficeOne(); // after being attended to/after being serviced
            // lineInOfficeTwo(); // and so on
            break;
        case EnrolleeType.OLD_STUDENT:
            // code goes here 
            break;
        case EnrolleeType.TRANSFEREE: 
            // code goes here
            break;
    }
}

对于每个 Enrollee 对象,我希望他们在他们需要进入的当前办公室的最短服务通道上排队。而且我认为我已经在我的 Office 类中成功地创建了一个方法 --- 它返回具有最短登记者队列的 ServiceLane 对象。

然而,问题一在于延迟所有Enrollee对象的入队方法。在现实生活中,登记者无法立即到达办公楼。登记者需要时间去那里。我打算使用计时器,但我不确定如何执行此操作。我试过了。哈哈。当我已经生成了数百个对象时,我只能将一二三Enrollee 对象排入ServiceLane 队列。我是这样做的:

public void enroll(List<Office> offices)
{
    switch (walkingSpeed)
    {
        case EnrolleeWalkingSpeed.SLOW: divisor = 5; break;
        case EnrolleeWalkingSpeed.NORMAL: divisor = 3; break;
        case EnrolleeWalkingSpeed.FAST: divisor = 1; break;
    }

    timer.Elapsed += timer_Elapsed;

    /********************************************************************/
    /* REMINDER: Update currentActivity every time the enrollee gets    */
    /*           into the next phase                                    */
    /*           Make an algorithm for choosing the shortest lane       */
    /*           (Office class's findShortestLane())                    */
    /********************************************************************/
    switch (type)
    {
        case EnrolleeType.NEW_STUDENT:
            performActivity(EnrolleeActivity.ACT1, offices.Find(office => office.getName().Equals("Admissions Office")));
            break;
        case EnrolleeType.TRANSFEREEE:
            performActivity(EnrolleeActivity.ACT1, offices.Find(office => office.getName().Equals("Admissions Office")));
            break;
        case EnrolleeType.OLD_STUDENT:
            performActivity(EnrolleeActivity.ACT9, offices.Find(office => office.getName().Equals("Finance Office")));
            break;
    }
}

private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
    if (counter % divisor == 0)
    {
        timer.Enabled = false;
        currentOffice.findShortestLane().enqueue(this);
        return;
    }

    counter++;
}

public void performActivity(EnrolleeActivity activity, Office office)
{
    this.currentActivity = activity;
    this.currentOffice = office;
    timer.Enabled = true;
}

问题二是如何延迟ServiceLane对象的出列过程。当然,我们需要足够的时间来处理请求。请注意,每个 ServiceLane 一次只能将它们出列一个。

问题三是如何让 Enrollee 对象仅在其所在的当前服务通道完成与 Enrollee 对象的请求(或者更确切地说,处理时间已经已达到/已过去)。

我确实知道要搜索什么,因此这个问题的标题更有可能令人困惑。我真的不知道我是否要使用线程或计时器或其他任何东西。可能一个关键字会有所帮助。还有一段代码告诉我应该如何解决这 3 个问题

【问题讨论】:

  • tl;博士。但看起来你混淆了实时和模拟时间。也许您应该查找“事件驱动模拟”

标签: c# multithreading timer simulation


【解决方案1】:

我认为您可以使用 Task 类来实现您的目标。 它有以毫秒为单位接受延迟时间的延迟方法,您可以在延迟时间之后设置 ContinuationTask,这里是示例:

Stopwatch sw = Stopwatch.StartNew();
var delay = Task.Delay(1000).ContinueWith(_ =>
                           { sw.Stop();
                             return sw.ElapsedMilliseconds; } );

Console.WriteLine("Elapsed milliseconds: {0}", delay.Result);

Here你可以找到更多关于Task类的信息,here是关于Delay方法的信息。希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 2012-06-25
    • 2017-07-25
    • 2014-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多