C# 通过套接字传输数据

C# 通过套接字传输数据,c#,silverlight,sockets,concurrency,monitor,C#,Silverlight,Sockets,Concurrency,Monitor,我想使用Socket 但是,我目前的实现遇到了并发性问题 public class Connection { private volatile bool readyToSend; private Queue<byte[]> q; private object bufferMonitor; public Connection { // initialize all things etc and connect } [

我想使用
Socket

但是,我目前的实现遇到了并发性问题

public class Connection {
    private volatile bool readyToSend;
    private Queue<byte[]> q;
    private object bufferMonitor;

    public Connection { 
        // initialize all things etc and connect
    }

    [...] // some other functions which are irrelevant for this problem

    private void ClientConnected (SocketAsyncEventArgs args) {
        // called by Thread A
        [...]
        readyToSend = true;
        WaitingForResponse(args);
    }

    private void WaitingForResponse (SocketAsyncEventArgs) {
        // called by Thread A
        if (q.Count == 0) {
            lock (bufferMonitor) {
                Monitor.Wait(bufferMonitor);
            }
        }
        if (q.Count != 0) {
            byte[] data;
            lock (q) {
                data = q.Dequeue();
            }
            args.SetBuffer(0, data.Length);
            args.ConnectSocket.SendAsync(args);
            // Will send all bytes and recall to WaitingForResponse afterwards
        } else {
            // Will recall this function if nothing happened.
        }
    }

    internal void SendIfConnected (byte[] data) {
        // called by Thread B
        if (readyToSend) {
            lock (q) {
                q.Enqueue(data);
            }
            lock (bufferMonitor) {
                Monitor.PulseAll(bufferMonitor);
            }
        }
    }        
}
公共类连接{
私有易失性bool-readyToSend;
专用队列q;
私有对象缓冲监视器;
公共连接{
//初始化所有事物等并连接
}
[…]//与此问题无关的其他一些函数
专用void客户端已连接(SocketAsyncEventArgs args args){
//由线程A调用
[...]
readyToSend=true;
等待响应(args);
}
私有void WaitingForResponse(SocketAsyncEventArgs){
//由线程A调用
如果(q.Count==0){
锁(缓冲监视器){
Monitor.Wait(缓冲监视器);
}
}
如果(q.Count!=0){
字节[]数据;
锁(q){
data=q.Dequeue();
}
参数SetBuffer(0,数据长度);
args.ConnectSocket.SendAsync(args);
//将发送所有字节并调用WaitingForResponse
}否则{
//如果没有发生任何事情,将调用此函数。
}
}
内部void SendIfConnected(字节[]数据){
//由线程B调用
如果(readyToSend){
锁(q){
q、 排队(数据);
}
锁(缓冲监视器){
Monitor.pulsell(缓冲监视器);
}
}
}        
}
此实现的问题很简单,当客户端连接时对
readyToSend
的更改在第二个线程中不可见-第二个问题是,如果在
SendIfConnected
函数中放置断点并手动将值更改为true,则
监视器.Wait()
即使执行Monitor.pulsell,也不会返回


此外,我认为应该存在一些简单的解决方案来解决我最初的问题,而使用byte[]队列进行直播的整个想法并不是最好的。如果您能为我提供更好的指导,我将不胜感激。

我忍不住觉得这里缺少了一些信息

  • 在给出的代码中,bufferMonitor从未初始化。如果没有在您没有包含的代码中完成,那么我希望锁调用会失败

  • 您似乎在说readyToSend从未设置为true。从提供的代码来看,这表明从未调用clientConnected方法,或者[…]在执行方法的该行之前正在抛出/返回。您确定正在呼叫clientConnected吗

  • “在那里放置断点”指的是什么

  • 据我所知,Monitor.Wait(假设已创建锁对象)只有在线程A进入等待状态后执行Monitor.pulsell时才会返回。你确定这是正在发生的一系列事件吗?如果在调用wait之前发生脉冲,线程将不会唤醒

  • 愚蠢的问题,但你确定你在同一个对象实例上调用它吗?那么队列是否已正确填充


  • -readyToSend实际上设置为true,但是线程B没有看到这个/Monitor.Pulsell在Monitor.Wait调用之前和之后被调用了多次。@Etan:愚蠢的问题,但是你确定在对象的同一实例上调用它吗?那么队列是否正确填充了?谢谢:P这就是问题所在。意外地,有两个实例,客户端总是连接到队列未填充的实例^^^如果您愿意,可以将您的评论作为答案重新发布,以便我可以接受。@Etan:我已更新了我的答案:)至少您发现了问题。