using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
public class SensorReading
{
public int SensorId { get; }
public double Value { get; }
public DateTime Timestamp { get; }
public SensorReading(int sensorId, double value)
{
SensorId = sensorId;
Value = value;
Timestamp = DateTime.Now;
}
}
public class SensorDataCollector
{
// Thread-safe collection for storing sensor readings
private readonly ConcurrentBag<SensorReading> _readings = new ConcurrentBag<SensorReading>();
// Object for additional synchronization if needed
private readonly object _lockObject = new object();
public void AddReading(SensorReading reading)
{
// Add reading to the thread-safe collection
_readings.Add(reading);
}
public double GetAverageValue(int sensorId)
{
// Use LINQ for thread-safe filtering and averaging
var sensorReadings = _readings.Where(r => r.SensorId == sensorId);
return sensorReadings.Any() ? sensorReadings.Average(r => r.Value) : 0;
}
public int GetTotalReadingCount()
{
// Return total number of readings
return _readings.Count;
}
}
class Program
{
static void Main(string[] args)
{
// Create a single instance of SensorDataCollector
SensorDataCollector collector = new SensorDataCollector();
// Random number generator for values and delays
Random random = new Random();
// Create an array to hold our tasks
Task[] sensorTasks = new Task[5];
// Create tasks for each sensor
for (int i = 0; i < 5; i++)
{
int sensorId = i + 1; // Sensor IDs from 1 to 5
sensorTasks[i] = Task.Run(() =>
{
for (int j = 0; j < 50; j++)
{
// Generate a random sensor reading
double value = random.NextDouble() * 100; // Random value between 0 and 100
// Create sensor reading
SensorReading reading = new SensorReading(sensorId, value);
// Add reading to collector
collector.AddReading(reading);
// Random delay between 100-300 ms
Thread.Sleep(random.Next(100, 301));
}
});
}
// Wait for all sensor tasks to complete
Task.WaitAll(sensorTasks);
// Display results
Console.WriteLine($"Total number of readings: {collector.GetTotalReadingCount()}");
// Display average value for each sensor
for (int i = 1; i <= 5; i++)
{
double avgValue = collector.GetAverageValue(i);
Console.WriteLine($"Average value for Sensor {i}: {avgValue:F2}");
}
}
}A. Vláknově bezpečný systém pro sběr a analýzu dat ze senzorů
Navrhněte systém pro sběr dat z více senzorů, které běžíparalelně a v reálném čase posílají měření do centrálního sběrače dat. Cílem je zajistit vláknově bezpečný zápis a čtenídat, a zároveň umožnit jednoduchou analýzu dat.
Třída SensorReading
Reprezentuje jedno měření ze senzoru. Obsahuje:
• int Sensor Id
double Value
• DateTime Timestamp
Pro získání aktuálního času můžete použít příkaz: DateTime
localDate = DateTime.Now;
Třída SensorDataCollector
Tato třída bude sdílená mezi vlákny a musí být vláknově bezpečná.
Vnitřní struktura:
• Uchovávejte všechna měření v kolekci např.
List
Požadované metody:
• void AddReading (Sensor Reading reading)
• Přidá nové měření do kolekce.
• Tato metoda bude volána z více vláken současně.
double GetAverageValue(int sensorId)
• Vrátí průměrnou hodnotu všech měření od daného senzoru.
• int GetTotalReadingCount()
• Vrátí celkový počet uložených měření.
Všechny metody musí být správně synchronizované, aby při paralelním čtení a zápisu nedošlo k výjimkám nebo aby nebyla ukládána chybná data.
Všechny metody musí být správně synchronizované, aby při paralelním čtení a zápisu nedošlo k výjimkám nebo aby nebyla ukládána chybná data.
Metoda Main
• Vytvořte instanci třídy Sensor DataCollector.
Spusťte 5 paralelních Tasků nebo Threadů, z nichž každý simuluje 1 senzor:
• Každý senzor každých 100-300 ms generuje nové měření (s náhodnou hodnotou) a přidá jej do collectoru.
• způsob volby ID senzoru je na Vás.
• Každý senzor nechte vygenerovat 50 hodnot.
Po dokončení zobrazte:
Celkový počet měření
Průměrnou hodnotu z každého senzoru
B. Vláknově bezpečný Chat server
Navrhněte jednoduchý chat server, do kterého mohou uživatelé posílat zprávy paralelně, a ostatní uživatelé si mohou zobrazit historii zpráv. Hlavním cílem je vytvořit vláknově bezpečnou správu zpráv, aby se žádná zpráva neztratila a nevznikly duplicity.
Třída Message
Reprezentuje jednu zprávu odeslanou uživatelem.
string Sender
string Text
DateTime Timestamp
Pro získání aktuálního času můžete použít příkaz: DateTime
localDate = DateTime.Now;
Třída ChatRoom
Třída, která uchovává zprávy a musí být vláknově bezpečná.
Třída Message
Reprezentuje jednu zprávu odeslanou uživatelem.
string Sender
string Text
DateTime Timestamp
Pro získání aktuálního času můžete použít příkaz: DateTime
localDate = DateTime.Now;
Třída ChatRoom
Třída, která uchovává zprávy a musí být vláknově bezpečná.
Vnitřní struktura:
Zprávy uchovávejte ve vhodné kolekci (List
• Použijte vlastní synchronizaci lock, Monitor, apod.
Povinné metody:
• void AddMessage(Message msg)
• Přidá zprávu do chatu.
• Bude volána z více vláken současně.
• List
• Vrátí všechny zprávy od určitého uživatele.
• int GetMessageCount()
• Vrátí počet přijatých zpráv.
Všechny metody musí být správně synchronizované, aby při paralelním čtení a zápisu nedošlo k výjimkám nebo aby nebyla ukládána chybná data.
Metoda Main
Vytvořte sdílenou instanci Chat Room.
Simulujte 5 uživatelů pomocí Task nebo Thread, každý uživatel bude:
• Ve smyčce posílat zprávy do místnosti (10 zpráv s pauzou 100-300 ms).
• Jméno uživatele (sender) bude jedinečné pro každý Task.
Po ukončení simulace vypište:
• Celkový počet zpráv.
• Počet zpráv od každého uživatele.
Všechny zprávy od jednoho z uživatelů.
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Linq;
// Třída reprezentující zprávu v chatu
public class Message
{
public string Sender { get; }
public string Text { get; }
public DateTime Timestamp { get; }
public Message(string sender, string text)
{
Sender = sender;
Text = text;
Timestamp = DateTime.Now;
}
}
// Vláknově bezpečná třída ChatRoom
public class ChatRoom
{
// Použití thread-safe kolekce
private readonly List<Message> _messages;
private readonly object _lockObject;
public ChatRoom()
{
_messages = new List<Message>();
_lockObject = new object();
}
// Synchronizovaná metoda pro přidání zprávy
public void AddMessage(Message msg)
{
lock (_lockObject)
{
_messages.Add(msg);
}
}
// Synchronizovaná metoda pro získání zpráv od konkrétního odesílatele
public List<Message> GetMessagesFrom(string sender)
{
lock (_lockObject)
{
return _messages.Where(m => m.Sender == sender).ToList();
}
}
// Synchronizovaná metoda pro získání počtu zpráv
public int GetMessageCount()
{
lock (_lockObject)
{
return _messages.Count;
}
}
}
class Program
{
static void Main()
{
// Vytvoření sdílené instance ChatRoom
ChatRoom chatRoom = new ChatRoom();
// Definice pole jmen uživatelů
string[] userNames = { "Alice", "Bob", "Charlie", "David", "Eve" };
// Vytvoření úloh pro simulaci uživatelů
var tasks = userNames.Select(userName => Task.Run(() =>
{
Random random = new Random();
for (int i = 0; i < 10; i++)
{
// Generování náhodných zpráv s pauzou
string message = $"Zpráva {i + 1} od {userName}";
chatRoom.AddMessage(new Message(userName, message));
// Náhodná pauza mezi 100-300 ms
Thread.Sleep(random.Next(100, 301));
}
})).ToArray();
// Čekání na dokončení všech úloh
Task.WaitAll(tasks);
// Výpis celkového počtu zpráv
Console.WriteLine($"Celkový počet zpráv: {chatRoom.GetMessageCount()}");
// Výpis počtu zpráv pro každého uživatele
foreach (string userName in userNames)
{
int userMessageCount = chatRoom.GetMessagesFrom(userName).Count;
Console.WriteLine($"Počet zpráv od {userName}: {userMessageCount}");
}
// Výpis všech zpráv od jednoho uživatele (např. Alice)
Console.WriteLine("\nZprávy od Alice:");
var aliceMessages = chatRoom.GetMessagesFrom("Alice");
foreach (var msg in aliceMessages)
{
Console.WriteLine($"{msg.Timestamp}: {msg.Text}");
}
}
}