【问题标题】:Streaming data over sockets通过套接字流式传输数据
【发布时间】:2011-03-28 10:32:29
【问题描述】:

我想使用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);
            }
        }
    }        
}

这个实现的问题很简单,当客户端连接时对readyToSend 的更改在第二个线程中不可见 - 第二个问题是,如果您在SendIfConnected 函数中放置一个断点并更改手动将值设置为 true,即 Monitor.Wait() 将永远不会返回,尽管 Monitor.PulseAll 已执行。

另外,我有点认为应该有一些简单的解决方案来解决我最初的问题,并且使用 byte[] 队列进行直播的整个想法并不是最好的。如果有任何更好的方向,我将不胜感激。

【问题讨论】:

    标签: c# silverlight sockets concurrency monitor


    【解决方案1】:

    我不禁觉得这里缺少一些信息。

    1. 在给出的代码中,bufferMonitor 从未初始化。如果它没有在您未包含的某些代码中完成,那么我预计锁定调用会失败。

    2. 您似乎在说 readyToSend 永远不会设置为 true。从提供的代码来看,这表明 clientConnected 方法永远不会被调用,或者 [...] 在执行该方法的那一行之前正在抛出/返回。您确定正在调用 clientConnected 吗?

    3. “在此处设置断点”指的是哪里?

    4. 据我了解,Monitor.Wait(假设已创建锁对象)只有在执行 Monitor.PulseAll 时才会返回,此时线程 A 已进入等待状态。你确定这是正在发生的事件的顺序吗?如果在调用 wait 之前发生脉冲,则线程不会唤醒。

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

    【讨论】:

    • - readyToSend 实际上设置为 true,但线程 B 看不到这个 / Monitor.PulseAll 在 Monitor.Wait 调用之前和之后被多次调用。
    • @Etan:愚蠢的问题,但你确定你是在同一个对象实例上调用它吗?所以队列填充正确?
    • 谢谢:P 这就是问题所在。意外地,有两个实例,客户端总是连接到一个队列没有填充的实例^^如果你愿意,你可以将你的评论作为答案重新发布,这样我就可以接受了。
    • @Etan:我已经更新了我的答案 :) 至少你找到了问题。
    猜你喜欢
    • 2014-07-23
    • 2014-01-18
    • 2011-02-14
    • 2013-04-27
    • 1970-01-01
    • 1970-01-01
    • 2020-09-23
    • 2014-06-28
    • 2014-10-19
    相关资源
    最近更新 更多