- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我需要将对套接字的 BeginSend 调用排队,并且我需要它们按时间顺序执行。为此,我使用信号量在回调函数可以运行时发出信号。
大多数情况下它是有效的,因为每个异步回调都在一个单独的线程上执行,但偶尔在新的异步调用中使用当前回调中使用的相同线程。发生这种情况时,该线程将被锁定,等待信号量被释放,但由于本应清除信号量的同一个线程正在等待信号量被清除,该线程将永远被锁定。
这里为了说明问题是一段测试代码:
static Semaphore semaphore = new Semaphore(1, 1);
static IList<byte[]> buffer = new List<byte[]>();
static void Main()
{
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Connect(new IPEndPoint(new IPAddress(new byte[] { 192, 168, 1, 8 }), 123));
while (true) // data feed
{
lock (buffer)
{
buffer.Add(new byte[1460]);
if (buffer.Count == 1)
socket.BeginSend(buffer[0], 0, 1460, 0, new AsyncCallback(SendCallback), socket); // calls BeginSend if the buffer was empty before
}
}
}
static void SendCallback(IAsyncResult ar)
{
Console.WriteLine("in " + Thread.CurrentThread.ManagedThreadId);
semaphore.WaitOne();
Socket socket = (Socket)ar.AsyncState;
lock(buffer)
{
buffer.RemoveAt(0); // removes data that was sent
if (buffer.Count > 0) // if there is more data to send calls BeginSend again
socket.BeginSend(buffer[0], 0, 1460, 0, new AsyncCallback(SendCallback), socket);
}
semaphore.Release();
Console.WriteLine("out " + Thread.CurrentThread.ManagedThreadId);
}
这是输出:
因为线程 10 被转移到一个新的回调,没有给之前的回调退出和清除信号量的机会,线程被永远锁定。
我该如何解决这个问题?
最佳答案
切换到任务:
不错的 msdn 文章 Tasks and the APM Pattern
public Task<int> SendAsync(Socket socket, byte[] buffer, int offset, int size, SocketFlags flags)
{
var result = socket.BeginSend(buffer, offset, size, flags, _ => { }, socket);
return Task.Factory.FromAsync(result,(r) => socket.EndSend(r));
}
现在事情变得容易了一些:
使用默认 BlockingCollection<>作为并发队列。它是线程保存并删除列表上的显式锁定
static BlockingCollection<byte[]> buffer = new BlockingCollection<byte[]>();
public async void Main()
{
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Connect(new IPEndPoint(new IPAddress(new byte[] { 192, 168, 1, 8 }), 123));
while (!buffer.IsCompleted)
{
var data = buffer.Take();
await SendAsync(socket, data, 0, data.Length, 0);
}
Console.ReadLine();
}
在不需要信号量的情况下保持非阻塞发送和顺序。
关于c# - 排队调用套接字的异步方法 BeginSend,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23455992/
我想了解以下方面的一些信息: Socket.BeginSend Method (array[]()[], Int32, Int32, SocketFlags, AsyncCallback, Objec
我需要将对套接字的 BeginSend 调用排队,并且我需要它们按时间顺序执行。为此,我使用信号量在回调函数可以运行时发出信号。 大多数情况下它是有效的,因为每个异步回调都在一个单独的线程上执行,但偶
我是编程新手,对异步套接字编程感到困惑。 例如,假设我有两个 BeginSend,一个接一个。第一个发送一百万个字符,第二个仅发送 64 个字符。 由于异步性质,第二个 BeginSend 不会在第一
所以我明白 Send 是同步的,而 BeginSend 是异步的。我听说套接字发送方法的数据传输速度比 BeginSend 快(注意:我不是在谈论 CPU 性能,而只是发送和接收数据包延迟)。谁能告诉
我正在编写一个套接字应用程序,它可以同时异步轮询多个服务器并向用户报告它们状态的任何变化。到目前为止,一切正常,除了一个我似乎无法弄清楚的小错误。 服务器每 10 秒创建一组套接字,然后调用异步连接。
我的 TCP ping/pong 工作正常,但在尝试添加第二种数据类型后,我遇到了接收程序从未触发 BeginReceive 回调的情况。 代码是相同的,除了第二个(有问题的)数据类型,序列化是提前完
当我向远程 机器发送大量数据时,发送回调几乎立即执行。 [05:10:35:981] ChildSocket.Send(): Sending 1048508 bytes. [05:10:35:988]
这是一个我不太明白的异步套接字场景...我有 2 个 Tcp 套接字,一个客户端套接字和一个服务器套接字。我的服务器套接字已绑定(bind)并正在监听端口。 我的客户端套接字连接到服务器套接字(使用
比如说,我有一个类,它包装了一个 Socket 并且(除其他外)执行异步数据发送。 我按以下方式执行发送(大大简化 - 无错误处理等): private Socket _socket; public
我使用以下代码异步发送数据,但我注意到在从 asyncRes 获取的 AsyncWaitHandle 中使用 WaitOne 根本不等待。我检查了 MSDN,它说我应该使用 ManualResetEv
.NET 中的 Socket 类公开了以下方法: Socket.BeginSend Method (IList>, SocketFlags, AsyncCallback, Object) 我有一个返回
这里的工作代码 static MessageSender TopicClient; public static void SendTopicMessage(BrokeredMessage messag
这里的工作代码 static MessageSender TopicClient; public static void SendTopicMessage(BrokeredMessage messag
例。 http://msdn.microsoft.com/en-us/library/bew39x2a%28v=vs.110%29.aspx我想知道像 BeginSend、BeginReceive 等
我是一名优秀的程序员,十分优秀!