Почему метод receive не блокирует поток?

216
02 мая 2018, 03:05

Чего хочу: получить данные с удалённого модуля по сокету. Как реализую: пока в одном потоке, чтобы проще было делать отладку. Конечно, мой подход не супер гибкий, но цель - реализовать некую финкциональность, а не написать супер крутое ПО по паттернам и принципам SOLID. Так что архитектура такая:

Класс DataGenerator. У него есть публичные поля IsDataGenerated и Data. Алгоритм, по которому он "создаёт" данные: 1. Создаётся TCP-соединение с удалённым модулем. 2. Отправляет ему запрос. 3. Принимает данные. 4. Записывает в Data полученное значение. 5. Устанавли вает IsDataGenerated в true.

static class DataGenerator
{
    public static bool IsDataGenerated { get; private set; }
    public static string Data { get; private set; }
    static Socket _remoteDataGeneratorConnection = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    static IdsGenerator()
    {
        IsDataGenerated = false;
        ConnectSockets();
    }
    private static void ConnectSockets()
    {
        ConnectToDataGenerator();
    }
    private static void ConnectToDataGenerator()
    {
        IPAddress ipAddr = IPAddress.Parse(Settings.GetLocalIPAddress());
        IPEndPoint remoteDataGeneratorEndPoint = new IPEndPoint(ipAddr, /* port */ 48209);
        _remoteDataGeneratorConnection.Connect(remoteDataGeneratorEndPoint);
    }
    public static void GenerateData()
    {
        IsDataGenerated = false;
        SendRequestToGenerator(_remoteDataGeneratorConnection);
        Data = GetStringResponseFromSocket(_remoteDataGeneratorConnection);
        IsDataGenerated = true;
    }
    private static void SendRequestToGenerator(Socket socket)
    {
        byte[] msg = BitConverter.GetBytes(1);
        int bytesSent = socket.Send(msg);
    }
    private static string GetStringResponseFromSocket(Socket socket)
    {
        string receivedData = null;
        byte[] rcvLenBytes = new byte[sizeof(Int32)]; // 4 bytes - size of (received) Int32
        _remoteDataGeneratorConnection.Receive(rcvLenBytes);
        if (BitConverter.IsLittleEndian)
            Array.Reverse(rcvLenBytes);
        int receivingDataLength = System.BitConverter.ToInt32(rcvLenBytes, 0);
        byte[] bytes = new byte[receivingDataLength];
        int bytesReceived = _remoteDataGeneratorConnection.Receive(bytes); // returns count of received bytes
        if (bytesReceived != 0) // data received
            receivedData = Settings.SocketsDataEncoding.GetString(bytes, 0, bytesReceived); // converting byte array to string
        return receivedData;
    }
}

Как использую этот класс (да, способ костыльный; думала о событийной моделе, но сейчас не об этом):

private string GetData()
    {
        DataGenerator.GenerateData();
        while (!DataGenerator.IsDataGenerated)
        {
            Thread.Sleep(100);
        }
       return DataGenerator.Data;
    }

В чём проблема: хотя в коде нету явного создания потоков, вызовов асинхронных методов, но метод GetData() постоянно возвращает предыдущее значение. То есть сначала пустую строку, потом строку, которая была сгенерирована при первом запросе, хотя уже был отправлен второй, и т.д. Получается, где-то создаётся второй поток, а основной просто не ждёт его завершения, устанавливает IsDataGenerated в true и сразу же забирает старое значение. В отладке всё отлично работает. То есть второй поток успевает записать данные до получения их значения. Как заставить основной поток дождаться получения данных с сокета?

READ ALSO
Вывод в Double или Float

Вывод в Double или Float

Пользователь вводит вероятность и сумму ставки(оба натуральные числа)Вывести выигрыш нужно число с плавающей точкой, так же записать в базу...

214
WPF IObservable<T> как источник данных для ItemsSource

WPF IObservable<T> как источник данных для ItemsSource

У меня есть класс, реализующий интерфейс IObservableВ xaml разметке я указал объект этого класса, как источник данных для списка, однако содержимое...

188
c# winforms получить значение из нового окна

c# winforms получить значение из нового окна

есть 2 формына первой, допустим, кнопка открывающая 2-ю форму, на которой есть ползунок TrackBar

193
Полупрозрачный размытый фон с шумами

Полупрозрачный размытый фон с шумами

когда-то давно уже задавался этим вопросом, но без особых успеховРечь идёт о полупрозрачном размытом фоне, да ещё и с шумами(собственно как...

173