c# - 如何在 C# 中正确排队和执行具有可变开始时间的任务?

标签 c# multithreading

我还是 C# 新手。目前使用.NET 3.5。我正在编写一个在线游戏,我的游戏引擎需要处理玩家请求的单位移动。这些单位将以不同的速度移动,并且可以有不同的目的地,因此单位到达(以及命令完成)的实际时间会有很大差异。

我的策略是,模型将计算沿着给定路径的下一步移动,然后将工作人员排队以在单位到达该位置的同时执行。工作人员将更新单元、通知玩家、排队下一步等。

我最大的障碍之一是编写一个有条件执行任务的工作线程。过去,我的工作线程只是尝试尽快按顺序运行每个任务。另一个挑战是,单元移动可能会比队列中的任何其他任务具有更早的开始时间,因此显然,它们需要移动到队列的前面。

这是我到目前为止所想出的,它有效,但有一些限制,即它的 100 毫秒 sleep 限制了我的命令响应时间。我想要做的事情是否有一个模式,或者我是否遗漏了一些明显的东西?

谢谢!

public class ScheduledTaskWorker
{
    List<ScheduledTask> Tasks = new List<ScheduledTask>();

    public void AddTask(ScheduledTask task)
    {
        lock (Tasks)
        {
            Tasks.Add(task);
            Tasks.Sort();
        }
    }

    private void RemoveTask(ScheduledTask task)
    {
        lock (Tasks)
        {
            Tasks.Remove(task);
        }
    }

    private ScheduledTask[] CopyTasks()
    {
        lock (Tasks)
        {
            return Tasks.ToArray();
        }
    }


    public void DoWork()
    {
        while (!StopWorking)
        {
            ScheduledTask[] safeCopy = CopyTasks();

            foreach (ScheduledTask task in safeCopy)
            {
                if (task.ExecutionTime > DateTime.Now) 
                    break;

                if (ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadPoolCallBack), task))
                    RemoveTask(task);
                else
                {
                    // if work item couldn't be queued, stop queuing and sleep for a bit
                    break;
                }
            }

            // sleep for 100 msec so we don't hog the CPU. 
            System.Threading.Thread.Sleep(100);
        }
    }

    static void ThreadPoolCallBack(Object stateInfo)
    {
        ScheduledTask task = stateInfo as ScheduledTask;
        task.Execute();
    }

    public void RequestStop()
    {
        StopWorking = true;
    }

    private volatile bool StopWorking;
}

还有任务本身...

public class ScheduledTask : IComparable
{
    Action<Item> Work;
    public DateTime ExecutionTime;
    Item TheItem;

    public ScheduledTask(Item item, Action<Item> work, DateTime executionTime)
    {
        Work = work;
        TheItem = item;
        ExecutionTime = executionTime;
    }

    public void Execute()
    {
        Work(TheItem);
    }

    public int CompareTo(object obj)
    {
        ScheduledTask p2 = obj as ScheduledTask;
        return ExecutionTime.CompareTo(p2.ExecutionTime);
    }

    public override bool Equals(object obj)
    {
        ScheduledTask p2 = obj as ScheduledTask;
        return ExecutionTime.Equals(p2.ExecutionTime);
    }

    public override int GetHashCode()
    {
        return ExecutionTime.GetHashCode();
    }
}

最佳答案

我并不反对克里斯的观点,他的回答可能更适合您的根本问题。

但是,要回答您的具体问题,您可以使用类似于 Java 的 DelayQueue 的内容。 ,它看起来已在此处移植到 C#:http://code.google.com/p/netconcurrent/source/browse/trunk/src/Spring/Spring.Threading/Threading/Collections/Generic/DelayQueue.cs?spec=svn16&r=16

您的Task类将实现 IDelayed那么您可以有一个线程调用 Take(在没有准备好项目时会阻塞)并执行任务,或者将它们传递给 ThreadPool.QueueUserWorkItem .

关于c# - 如何在 C# 中正确排队和执行具有可变开始时间的任务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7629849/

相关文章:

c# - propertyInfo.PropertyType 和 propertyInfo.GetType 之间有什么区别?

multithreading - 生产者/消费者模型是否等同于 Actor ?

c - 多线程中使用的套接字?

c++ - shared_timed_mutex 在 OS X 10.11.2 上不可用?

c# - 如何使用 Linqpad 插入具有指定主键的记录?

c# - 为什么这个 NUnit+Moq 测试失败?

c# - 我是否应该始终在 nhibernate 中使用事务(即使是简单的读写)?

c# - 无法让 NServiceBus 在自定义服务帐户下运行?

c++ - 在什么情况下,您在 C++ 中使用信号量而不是互斥量?

java线程通知