【发布时间】:2017-07-26 10:20:05
【问题描述】:
我的应用程序因“无法关闭未初始化的消息”未处理异常而崩溃。这可能是由于从多个线程访问套接字。
我在调试这个问题时遇到问题,因为当我查看我的代码时,所有对套接字的访问都是在轮询线程中完成的——直接在 ReceiveReady 事件处理程序中(根据我的理解,它在轮询线程上运行)或在手动创建 Task (new Task(...)) 然后在轮询线程 (task.Start(poller)) 上启动。
所以我看不到可能发生这种情况的地方。
第二个问题是未处理的异常——我将所有发送/接收都包装在 try-catch 中,但异常发生在外面的某个地方。
我正在寻找如何有效地调试它并找出我的代码中行为不端的地方。
代码示例——正如我所写的,我只使用了两个“模式”:
直接使用 poller 线程(感谢 poller 线程上触发的事件):
private async void OnMessageReceiveReady(object sender, NetMQSocketEventArgs args)
{
NetMQSocket socket = args.Socket;
NetMQMessage mq_msg = socket.ReceiveMultipartMessage();
...
从任意线程切换到poller的线程:
Task sending = new Task(() =>
{
foreach (NetMQFrame address in mq_envelope)
socket.SendMoreFrame(address.ConvertToString());
socket.SendFrame(response_data);
});
sending.Start(this.sharedPoller);
await sending.ConfigureAwait(false);
【问题讨论】:
-
你能给我们展示一些相关的代码吗(尽可能多)?
-
代码是否锁定在您读取/写入接收数据的位置? ReceiveReady 事件处理程序应该很少处理数据。它应该读取数据并放入缓冲区并继续。缓冲区的处理应该在不同的线程或主代码中处理。
-
@mjwills,我更新了问题——我多次使用此代码,仅此而已。
-
@jdweng,你的意思是像
lock命令?不,事件是在 poller 的线程上触发的,所以在给定的时间可能只有一个在运行,对吗?感谢您的提示,但它涉及性能问题,而不是多线程执行。是否有可能因为ReceiveReady代码需要更多时间而得到这样的异常? -
TCP 数据报的最大大小约为 1500 字节。您可以获得零字节的数据报(保持活动消息),数据报可以拆分为小数据报并由路由器和服务器组合。所以发送的数据并不总是会被接收到。所以接收解析器必须足够聪明才能处理部分消息。我的 ReceiveReady 方法我只是将需要的数据添加到 List
对象。然后有一个解析器然后删除一个一次从 List .Ascii 数据中读取消息,我的解析器将从 List 读取,直到找到第一个返回。然后删除锁定代码中的行,因此 RxReady 被锁定。
标签: c# multithreading sockets debugging netmq