使用C#的新异步功能等待网络数据包的最佳方法是什么
我最近一直在玩新的Async CTP,我遇到过一种我不确定如何继续的情况.
在我目前的代码库中,我使用的是“作业”和“作业管理器”的概念.作业仅用于处理初始消息,发送响应,然后等待响应. 我已经有了基于同步套接字的现有代码,其中网络线程正在等待数据到达,然后将其传递给事件处理程序,最终传递给作业管理器. 作业管理器查找将处理消息的作业,并将其传递. 所以场景是这样的: >工作经理获得新消息并启动工作. 这是一个伪代码示例: class MyJob : Job { public override void RunJob( IPacketMsg packet ) { // handle packet var myReply = new Packet(); SendReply( myReply ); await GetResponse(); } } 但我不完全确定如何在第3步继续.工作经理将获得响应,然后将其交给正在运行的工作.但我不知道如何让工作等待回应. 我考虑过创建一个等待在WaitHandle上阻塞的任务,但这是最好的解决方案吗? 在这种情况下我还能做些什么吗? 编辑 解决方法
首先,我应该提到Async CTP非常好地处理异步操作,但异步事件并没有那么多.您可能想要考虑基于Rx的方法.但是让我们继续使用Async CTP. 您有两个基本选项来创建任务: >有代表.例如,Task.Factory.StartNew将在线程池上运行委托.自定义任务工厂和调度程序为任务委托提供了更多选项(例如,指定委托必须在STA线程上运行). 如果作业处理受CPU约束,则将其传递给Task.Factory.StartNew是有意义的.我将假设作业处理受CPU限制. 工作管理员伪代码: // Responds to a new message by starting a new job on the thread pool. private void RespondToNewMessage(IPacketMsg message) { IJob job = ..; Task.Factory.StartNew(job.RunJob(message)); } // Holds tasks waiting for a response. private ConcurrentDictionary<int,TaskCompletionSource<IResponse>> responseTasks = ..; // Asynchronously gets a response for the specified reply. public Task<IResponse> GetResponseForReplyAsync(int replyId) { var tcs = new TaskCompletionSource<IResponse>(); responseTasks.Add(replyId,tcs); return tcs.Task; } // Responds to a new response by completing and removing its task. private void RespondToResponse(IResponse response) { var tcs = responseTasks[response.ReplyId]; responseTasks.Remove(response.ReplyId); tcs.TrySetComplete(response); } 这个想法是,工作经理还管理一系列优秀的回复.为了实现这一点,我引入了一个简单的int reply标识符,作业管理器可以使用该标识符来确定响应哪个响应. 现在工作可以像这样工作: public override void RunJob(IPacketMsg packet) { // handle packet var myReply = new Packet(); var response = jobManager.GetResponseForReplyAsync(myReply.ReplyId); SendReply(myReply); await response; } 因为我们将作业放在线程池线程上,所以有一些棘手的事情: >必须在发送回复之前调用GetResponseForReplyAsync(注册任务),然后等待.这是为了避免在我们有机会注册之前发送回复和收到回复的情况. 如果作业足够短,不需要将它们放在线程池线程上,那么可以简化解决方案. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |