Потоковая передача данных через сокеты - PullRequest
2 голосов
/ 28 марта 2011

Я хочу транслировать данные в реальном времени с одного сервера на несколько клиентов, используя 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 выполняется.

Кроме того, я вроде думаю, что должно существовать какое-то простое решение моей исходной проблемы и что вся идея использования байтовой очереди [] дляПрямая трансляция не самая лучшая.Я был бы признателен за любую точку в лучшем направлении.

1 Ответ

1 голос
/ 28 марта 2011

Не могу помочь, но чувствую, что здесь не хватает какой-то информации.

  1. В приведенном коде bufferMonitor никогда не инициализируется.Если это не будет сделано в каком-то коде, который вы не включили, то я ожидаю, что вызов блокировки завершится неудачей.

  2. Похоже, вы говорите, что readyToSend никогда не устанавливается вправда.Из предоставленного кода можно предположить, что метод clientConnected никогда не вызывается или [...] выбрасывает / возвращает до выполнения этой строки метода.Вы уверены, что clientConnected вызывается?

  3. Куда относится «установка точки останова»?

  4. Насколько я понимаю,Monitor.Wait (при условии, что объект блокировки был создан) будет возвращаться только в том случае, если Monitor.PulseAll выполняется после того, как поток A перешел в состояние ожидания.Вы уверены, что это последовательность событий, которая происходит?Если импульс возникает до вызова wait, поток не проснется.

  5. Глупый вопрос, но вы уверены, что вызываете его для того же экземпляра объекта?То есть очередь заполнена правильно?

...