在C#中限制方法我有一个游戏框架,它有一个实现IBotInterface的机器人列表。这些机器人由用户定制,唯一的限制是它们必须实现接口。然后,游戏会调用机器人中的方法(希望是并行的)来处理各种事件,例如yourTurn和roundStart。我希望机器人在被迫退出计算之前只花费有限的时间来处理这些事件。我正在尝试的一个例子是:(其中NewGame是代表)Parallel.ForEach(Bots,delegate(IBotbot){NewGamedel=bot.NewGame;IAsyncResultr=del.BeginInvoke(Info,null,null);WaitHandleh=r.AsyncWaitHandle;h.WaitOne(RoundLimit);if(!r.IsCompleted){del.EndInvoke(r);}});在这种情况下,我被迫运行可能不会终止的EndInvoke()。我想不出一种方法来彻底中止线程。如果有try{bot.NewGame(Info);形式的东西就好了}catch(TimeOutException){//告诉机器人关闭。}finally{//计算事物。但我认为不可能做出这样的结构。这样做的目的是优雅地处理具有意外无限循环或需要很长时间计算的AI。解决这个问题的另一种可能方法是使用类似(使用更多的c#和更少的伪代码)ClassActionThread{publicThreadthread{get;放;}publicQueuequeue{get;放;}publicvoidRun(){while(true){queue.WaitOne();动作a=queue.dequeue();A();}}Classfoo{main(){....foreach(BotbinBots){ActionThreada=getActionThread(b.UniqueID);NewGamedel=b.NewGame;a.queue.queue(del);}Thread.Sleep(1000);foreach(ActionThreadainThreads){a.Suspend();}不是最干净的方法,但它会起作用。(我会担心如何传递参数并稍后获取返回值)。[进一步编辑]我不太确定应用程序域是什么,从外观上看我可以做到,但看不出它有什么帮助我希望不要指望恶意代码。试图杀死其他机器人线程并不是赢得比赛的有效方式。我只是想给每个机器人一秒钟的时间来进行计算,然后继续游戏流程,所以这里的代码主要是慢速或错误代码。我试图看看我可以用Task做什么,慢慢地到达某个地方。我将阅读有关CAS可以做什么的信息,谢谢你们[更多编辑]我的头很痛,我似乎无法再思考或编写代码了。我正在为每个机器人构建一个专用线程的消息传递系统,并将暂停/休眠我已经决定在完全套接字服务器客户端系统上的那些线程。这样客户端就可以为所欲为,如果它拒绝回复服务器消息,我就忽略它。太糟糕了,它不得不走到这一步。不幸的是,没有100%安全的方法可以像您希望的那样干净地终止线程。尝试此操作的方法有很多,但它们都有一些您可能需要考虑的副作用和缺点。唯一干净、安全和认可的方法是获得相关线程的合作并友好地询问它。但是,如果您控制代码,这只是100%保证的方式。既然你不是,你就不会。这就是问题。让我们看看为什么合作也不是100%。假设有问题的线程通常需要调用您的库代码才能绘制到屏幕或类似的东西。您可以轻松检查这些方法并抛出异常。但是,异常可能会被捕获并吞下。或者有问题的代码可能会进入无法调用您的库代码的无限循环,这使您回到原点,如何在没有合作的情况下干净地杀死线程。我说过你不能。但是,有一种方法可行。您可以将机器人生成到它自己的进程中,然后在超时时终止该进程。这会给你更高的成功机会,因为至少操作系统会在进程终止时处理它管理的所有资源。你当然可以让这个过程在系统上留下损坏的文件,所以同样,它不是100%干净的。这是JoeDuffy的一篇博客文章,对这些问题进行了很多解释:托管代码和异步异常强化。.NET4.0Task为您提供了相当大的取消灵活性。在您已传递CancellationToken的任务中运行委托,如下所示。这是一个更全面的例子。编辑根据反馈,我认为正确的答案是遵循这个计划:使用CAS来限制AI,使其无法访问线程原语或弄乱文件。给它一个心跳回调,它在道德上有义务从长循环内部调用。如果线程耗时太长,此回调将抛出异常。如果AI超时,为它记录一个弱步,给它一个短时间来调用回调。如果没有,就让线程休眠直到下一轮。如果它永远不会突然消失,它将继续记录微弱的动作,直到进程将其作为后台线程杀死。利润!一种选择当然是自己启动新线程,而不是依赖BeginInvoke。您可以通过Thread.Join实现超时,并(毫不客气地)通过Thread.Abort终止线程(如有必要)。正如我在@Lasse的回答中提到的,您真的应该考虑使用代码访问安全来限制允许机器人在您的系统上执行的操作。您确实可以限制允许机器人执行的操作(包括删除它们访问线程API的能力)。可能值得将每个bot视为病毒,因为您无法控制它对您的系统执行的操作,并且我假设您的游戏将作为完全信任的应用程序运行。也就是说,如果您限制每个机器人使用CAS执行的操作,您就可以终止线程而不必担心破坏您的系统。如果机器人陷入无限循环,我怀疑您唯一的办法就是终止线程,因为它将无法以编程方式访问任何检查Thread.Abort信号的代码。这篇MSDN文章可能会为您提供一些有关如何使用TerminateThread函数更有效地终止失控线程的指示。你真的必须尝试所有这些事情并向自己证明哪一个可能是最好的解决方案。或者,如果这是一个竞争性游戏并且机器人作者必须公平,您是否考虑过让游戏给每个机器人一个“回合标记”,机器人必须呈现它想要调用的每个动作,并且当游戏翻转时,它是所有机器人都获得了新的令牌。这可能让您现在只需要担心失控的线程,而不是轮到它的机器人。编辑只需添加一个位置供人们查看安全许可标志枚举,您就会知道从哪里开始。如果您删除SecurityPermissionFlag.ControlThread权限(例如,仅授予执行代码的权限并排除ControlThread),您将删除他们在线程上使用某些高级操作的能力。我不知道不可行操作的程度,但周末进行一次有趣的练习可以解决这个问题。我认为唯一的问题是倒置条件。仅当任务成功完成时才应调用EndInvoke。粗略的建议:vargoodBots=newList();varresults=newIAsyncResult[Bots.Count];varevents=newWaitHandle[Bots.Count];诠释我=0;foreach(IBotbotinBots){NewGamedel=bot.NewGame;结果[i]=del.BeginInvoke(信息,空,空);事件[i++]=r.AsyncWaitHandle;}WaitAll(事件,RoundLimit);vargoodBots=newList();for(i=0;i更好的方法是为每个机器人显式启动一个线程,这样你就可以暂停行为不端的机器人(或降低它们的优先级),这样它们就不会继续从好的机器人那里窃取CPU时间。另一个设计选项可能是让每个robot都是自己的进程,然后使用IPC机制来交换数据。通常可以杀掉进程,不会有什么可怕的后果。以上是C#学习教程:C#中限制方法分享的所有内容,如果是对你有用,需要了解更多C#学习教程,希望大家多多关注。本文收集自网络,不代表立场,如涉及侵权,请点击右边管理员删除,如有转载请注明出处:
