Чего хочу: получить данные с удалённого модуля по сокету. Как реализую: пока в одном потоке, чтобы проще было делать отладку. Конечно, мой подход не супер гибкий, но цель - реализовать некую финкциональность, а не написать супер крутое ПО по паттернам и принципам 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 и сразу же забирает старое значение. В отладке всё отлично работает. То есть второй поток успевает записать данные до получения их значения. Как заставить основной поток дождаться получения данных с сокета?
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Пользователь вводит вероятность и сумму ставки(оба натуральные числа)Вывести выигрыш нужно число с плавающей точкой, так же записать в базу...
У меня есть класс, реализующий интерфейс IObservableВ xaml разметке я указал объект этого класса, как источник данных для списка, однако содержимое...
есть 2 формына первой, допустим, кнопка открывающая 2-ю форму, на которой есть ползунок TrackBar
когда-то давно уже задавался этим вопросом, но без особых успеховРечь идёт о полупрозрачном размытом фоне, да ещё и с шумами(собственно как...