Validation Exception Queue using MSMQ in C# - c#

I'm new in Microsoft Message Queue in Windows Server, I need to push, if the EmployeeID is NULL.
The Employee Model Class is
public class Employee
{
public string EmployeeID { get; set; }
public string EmployeeName { get; set; }
}
public void ValidationProcess(Employee emp)
{
if((emp != null) || (emp.EmployeeID == null))
{
// Push into Validation Exception Queue using MSMQ
}
}
Once the Data pushed into that Validation Exception Queue, it should be processed by separate process. Every 1hr the process need to initiate and it should call the following method
public void ValidationExceptionProcess(object obj)
{
// Some Inner Process
// Log the Error
}
Kindly guide me how to create and process it.

First Step:
Install MSMQs as a windows feature on the server/pc
Then:
- Create the queue if it does not exist
- Push the message in the queue asynchronously
Useful guide
Code example for pushing and retrieving messages from msmq:
public class ExceptionMSMQ
{
private static readonly string description = "Example description";
private static readonly string path = #".\Private$\myqueue";
private static MessageQueue exceptionQueue;
public static MessageQueue ExceptionQueue
{
get
{
if (exceptionQueue == null)
{
try
{
if (MessageQueue.Exists(path))
{
exceptionQueue = new MessageQueue(path);
exceptionQueue.Label = description;
}
else
{
MessageQueue.Create(path);
exceptionQueue = new MessageQueue(path);
exceptionQueue.Label = description;
}
}
catch
{
throw;
}
finally
{
exceptionQueue.Dispose();
}
}
return exceptionQueue;
}
}
public static void PushMessage(string message)
{
ExceptionQueue.Send(message);
}
private static List<string> RetrieveMessages()
{
List<string> messages = new List<string>();
using (ExceptionQueue)
{
System.Messaging.Message[] queueMessages = ExceptionQueue.GetAllMessages();
foreach (System.Messaging.Message message in queueMessages)
{
message.Formatter = new XmlMessageFormatter(
new String[] { "System.String, mscorlib" });
string msg = message.Body.ToString();
messages.Add(msg);
}
}
return messages;
}
public static void Main(string[] args)
{
ExceptionMSMQ.PushMessage("my exception string");
}
}
An other widely used way to do that would also be to use out of the box loggers which already contains this functionality like Enterprise Library or NLog which provide easy interfaces to do that.
For retrieving messages I would recommend a separate windows service which would periodically read messages and process them. An good example on how to do that is given here: Windows service with timer
Update: Windows Service Example:
MSMQConsumerService.cs
public partial class MSMQConsumerService : ServiceBase
{
private System.Timers.Timer timer;
public MSMQConsumerService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
this.timer = new System.Timers.Timer(30000D); // 30000 milliseconds = 30 seconds
this.timer.AutoReset = true;
this.timer.Elapsed += new System.Timers.ElapsedEventHandler(this.ProcessQueueMessages);
this.timer.Start();
}
protected override void OnStop()
{
this.timer.Stop();
this.timer = null;
}
private void ProcessQueueMessages(object sender, System.Timers.ElapsedEventArgs e)
{
MessageProcessor.StartProcessing();
}
}
and the MessageProcessor.cs
public class MessageProcessor
{
public static void StartProcessing()
{
List<string> messages = ExceptionMSMQ.RetrieveMessages();
foreach(string message in messages)
{
//write message in database
}
}
}

Related

websocket-sharp - OnMessage callback is not running in the main thread

I have a WPF (.NET Framework 4.6) application that uses websocket-sharp (version 3.0.0) to create a websocket server.
I have a WebsocketServer and using EventHandler to tranfer event to MainWindow.xaml.cs but it not working. The MainWindow.xaml.cs listened to a RaiseOnScanDevice event but not any event invoked here.
I think this issue is relative to different thread. I try using Dispatcher.Invoke but it still not working.
System.Windows.Application.Current.Dispatcher.Invoke(new System.Action(() =>
{
RaiseOnScanDevice(this, new EventArgs());
}));
I found an issue (https://github.com/sta/websocket-sharp/issues/350) but the answers do not resolve my issue.
Please help me a solution for this issue.
WebsocketServer.cs file
public class WebsocketServer : WebSocketBehavior
{
private static readonly Lazy<WebsocketServer> lazyInstance = new Lazy<WebsocketServer>(() => new WebsocketServer());
public static WebsocketServer Instance
{
get
{
return lazyInstance.Value;
}
}
private const string TAG = "WebsocketServer";
private const string HOST_IP_ADDRESS = "127.0.0.2"; // localhost
private const int PORT = 38001;
public WebSocketServer socket;
private PacketHandler packetHandler = new PacketHandler();
public event EventHandler<EventArgs> RaiseOnScanDevice = new EventHandler<EventArgs>((a, e) => { });
public WebsocketServer()
{
Initialize();
}
public void Initialize()
{
socket = new WebSocketServer(IPAddress.Parse(HOST_IP_ADDRESS), PORT);
socket.AddWebSocketService<WebsocketServer>("/");
StartServer();
}
public void StartServer()
{
socket.Start();
}
public void StopServer()
{
socket.Stop();
}
protected override Task OnOpen()
{
return base.OnOpen();
}
protected override Task OnClose(CloseEventArgs e)
{
return base.OnClose(e);
}
protected override Task OnError(ErrorEventArgs e)
{
return base.OnError(e);
}
protected override Task OnMessage(MessageEventArgs e)
{
System.IO.StreamReader reader = new System.IO.StreamReader(e.Data);
string message = reader.ReadToEnd();
//Converting the event back to 'eventName' and 'JsonPayload'
PacketModel packet = packetHandler.OpenPacket(message);
HandleMessageFromClient(packet);
return base.OnMessage(e);
}
private void HandleMessageFromClient(PacketModel packet) {
var eventName = packet.EventName;
var data = packet.Data;
if (eventName == null || eventName.Equals(""))
{
return;
}
switch (eventName)
{
case SocketEvent.Hello:
Send("OK");
break;
case SocketEvent.ScanDevice:
ScanDevice();
break;
default:
break;
}
}
private void ScanDevice()
{
try
{
RaiseOnScanDevice(this, new EventArgs());
// or dispatch to Main Thread
System.Windows.Application.Current.Dispatcher.Invoke(new System.Action(() =>
{
RaiseOnScanDevice(this, new EventArgs());
}));
}
catch (Exception exception)
{
Console.WriteLine(exception);
}
}
}
MainWindow.xaml.cs file
public partial class MainWindow : Window
{
public WebsocketServer WebsocketConnection
{
get { return WebsocketServer.Instance; }
}
public MainWindow()
{
InitializeComponent();
WebsocketConnection.RaiseOnScanDevice += SocketConnection_RaiseOnScanDevice;
}
private void SocketConnection_RaiseOnScanDevice(object sender, EventArgs e)
{
Console.WriteLine("SocketConnection_RaiseOnScanDevice");
}
The queue of messages is a good idea but you may want to use a lock to guard access to it. Most likely it won't be an issue but if you don't, you leave yourself open to the possibility of an error if the coroutine is reading from the queue as the websocket is writing to it. For example you could do something like this:
var queueLock = new object();
var queue = new Queue<MyMessageType>();
// use this to read from the queue
MyMessageType GetNextMessage()
{
lock (queueLock) {
if (queue.Count > 0) return queue.Dequeue();
else return null;
}
}
// use this to write to the queue
void QueueMessage(MyMessageType msg)
{
lock(queueLock) {
queue.Enqueue(msg);
}
}

How to instantiate a new Windows Form with Quartz.NET without problems?

I'm using the Quartz.NET library to create a job in my C# application.
I have some registers in my database, so I have a table wich contains a column called "start_date". The job runs every 50 seconds, so I compare the dates from the column "start_date" with the date of my computer, and if the dates are equal, I want to instantiate a new Windows Form with a message and a button.
At the moment, the new Windows Form is opening at the right moment, but the message is not showed and the window stops to respond.
Basically, in my code I have something like this:
FormMessage.cs
public partial class FormMessage : Form
{
public FormMessage()
{
InitializeComponent();
}
public FormMessage(double minutes)
{
InitializeComponent();
string message = string.Format("You have {0} minutes!", minutes);
lblMessage.Text = message ;
}
private void btnOK_Click(object sender, EventArgs e)
{
this.Close();
}
}
JobMessage.cs
public class JobMessage: IJob
{
List<Information> informations;
public void Execute(IJobExecutionContext context)
{
//Class with methods to get registers from database.
InformationAPI infoAPI = new InformationAPI();
informations = infoAPI.GetInformations();
foreach (Information info in informations)
{
DateTime computerDateTime = DateTime.Now;
DateTime infoDateTime = info.StartDate;
double difference;
if (DateTime.Compare(computerDateTime, infoDateTime) < 0)
{
difference = Math.Round(infoDateTime.Subtract(computerDateTime).TotalMinutes);
if (difference == 5)
{
FormMessage formMessage = new FormMessage(difference);
formMessage.Show();
}
}
}
}
}
Someone have some idea of the reason why the FormMessage window stops to respond?
Thank you for your attention!
You can try Quartz Listeners to let them open the form to show the data and keep the execution out of the job scope:
Action<IJobExecutionContext, JobExecutionException> listenerAction = (c, e) => {
var dataMap = context.GetJobDetail().GetJobDataMap();
var difference = dataMap.GetIntValue("difference");
FormMessage formMessage = new FormMessage(difference);
formMessage.Show();
}
var listener = new SyncJobListener(listenerAction);
And add the listener in to the scheduler:
scheduler.ListenerManager.AddJobListener(listener,
GroupMatcher<JobKey>.GroupEquals("GroupName"));
Using this SyncJobListener:
public class SyncJobListener : IJobListener
{
private readonly Action<IJobExecutionContext, JobExecutionException> _syncExecuted;
public string Name { get; private set; }
public SyncJobListener(
Action<IJobExecutionContext, JobExecutionException> syncExecuted
)
{
Name = Guid.NewGuid().ToString();
_syncExecuted = syncExecuted;
}
public void JobToBeExecuted(IJobExecutionContext context)
{
}
public void JobExecutionVetoed(IJobExecutionContext context)
{
}
public void JobWasExecuted(IJobExecutionContext context, JobExecutionException jobException)
{
_syncExecuted(context, jobException);
}
}
I have not tested this so if the dataMap does not have any data, you are going to need to allow the persistance:
[PersistJobDataAfterExecution]
[DisallowConcurrentExecution]
public class JobMessage: IJob {}

Enable Client to Talk to Server using the NetMQ "Realiable Pub/Sub" Pattern

I have a v4.0.0.1 implementation of Somdron's "Reliable Pub-Sub" pattern for communication between two parts of a new application. This application will have a "Server" (the engine that does all the heavy calculations) and "Clients" that will send requests and get information on progress back from the server.
The problem I have with my current version of "Reliable Pub-Sub" is that I don't seem to have a proper way for sending requests to the sever from the client. Let me start by showing you the code:
SERVER:
using NetMQ;
using NetMQ.Sockets;
using System;
using System.Linq;
namespace Demo.Messaging.Server
{
public class ZeroMqMessageServer : IDisposable
{
private const string WELCOME_MESSAGE = "WM";
private const string HEARTBEAT_MESSAGE = "HB";
private const string PUBLISH_MESSAGE_TOPIC = "PUB";
private readonly TimeSpan HEARTBEAT_INTERVAL = TimeSpan.FromSeconds(2);
private NetMQActor actor;
private NetMQTimer heartbeatTimer;
private XPublisherSocket publisher;
private NetMQPoller poller;
public ZeroMqMessageServer(string address)
{
Address = address;
actor = NetMQActor.Create(Start);
}
private void Start(PairSocket shim)
{
using (publisher = new XPublisherSocket())
{
publisher.SetWelcomeMessage(WELCOME_MESSAGE);
publisher.Bind(Address);
//publisher.ReceiveReady -= DropPublisherSubscriptions;
publisher.ReceiveReady += DropPublisherSubscriptions;
heartbeatTimer = new NetMQTimer(HEARTBEAT_INTERVAL);
heartbeatTimer.Elapsed += OnHeartbeatTimeElapsed;
shim.ReceiveReady += OnShimReceiveReady;
shim.SignalOK(); // Let the actor know we are ready to work.
poller = new NetMQPoller() { publisher, shim, heartbeatTimer };
poller.Run();
}
}
private void DropPublisherSubscriptions(object sender, NetMQSocketEventArgs e)
{
publisher.SkipMultipartMessage();
}
private void OnHeartbeatTimeElapsed(object sender, NetMQTimerEventArgs e)
{
publisher.SendFrame(HEARTBEAT_MESSAGE);
}
private void OnShimReceiveReady(object sender, NetMQSocketEventArgs e)
{
var socket = e.Socket;
string command = socket.ReceiveFrameString();
if (command == PUBLISH_MESSAGE_TOPIC)
{
// Forward the message to the publisher.
NetMQMessage message = socket.ReceiveMultipartMessage();
publisher.SendMultipartMessage(message);
}
else if (command == NetMQActor.EndShimMessage)
{
// Dispose command received, stop the poller.
poller.Stop();
}
}
public void PublishMessage(NetMQMessage message)
{
// We can use actor like NetMQSocket and publish messages.
actor.SendMoreFrame(PUBLISH_MESSAGE_TOPIC)
.SendMultipartMessage(message);
}
public string Address { get; private set; }
private bool disposedValue = false;
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
actor?.Dispose();
publisher?.Dispose();
poller?.Dispose();
}
disposedValue = true;
}
}
public void Dispose()
{
Dispose(true);
}
}
}
CLIENT:
using NetMQ;
using NetMQ.Sockets;
using System;
using System.Collections.Generic;
using System.Linq;
using Messaging.Helpers;
namespace Demo.Messaging.Client
{
public class ZeroMqMessageClient : IDisposable
{
private string SUBSCRIBE_COMMAND = "S";
private const string WELCOME_MESSAGE = "WM";
private const string HEARTBEAT_MESSAGE = "HB";
private const string PUBLISH_MESSAGE_TOPIC = "PUB";
private readonly TimeSpan TIMEOUT = TimeSpan.FromSeconds(5);
private readonly TimeSpan RECONNECTION_PERIOD = TimeSpan.FromSeconds(5);
private readonly string[] addressCollection;
private List<string> subscriptions = new List<string>();
private NetMQTimer timeoutTimer;
private NetMQTimer reconnectionTimer;
private NetMQActor actor;
private SubscriberSocket subscriber;
private PairSocket shim;
private NetMQPoller poller;
public ZeroMqMessageClient(params string[] addresses)
{
addressCollection = addresses;
actor = NetMQActor.Create(Start);
}
private void Start(PairSocket shim)
{
this.shim = shim;
shim.ReceiveReady += OnShimReceiveReady;
timeoutTimer = new NetMQTimer(TIMEOUT);
timeoutTimer.Elapsed += OnTimeoutTimerElapsed;
reconnectionTimer = new NetMQTimer(RECONNECTION_PERIOD);
reconnectionTimer.Elapsed += OnReconnectionTimerElapsed;
poller = new NetMQPoller() { shim, timeoutTimer, reconnectionTimer };
shim.SignalOK();
Connect();
poller.Run();
if (subscriber != null)
subscriber.Dispose();
}
private void Connect()
{
using (NetMQPoller tmpPoller = new NetMQPoller())
{
List<SubscriberSocket> socketCollection = new List<SubscriberSocket>();
SubscriberSocket connectedSocket = null;
EventHandler<NetMQSocketEventArgs> messageHandler = (s, e) =>
{
connectedSocket = (SubscriberSocket)e.Socket;
tmpPoller.Stop();
};
// We cancel the poller without setting the connected socket.
NetMQTimer tmpTimeoutTimer = new NetMQTimer(TIMEOUT);
tmpTimeoutTimer.Elapsed += (s, e) => tmpPoller.Stop();
tmpPoller.Add(tmpTimeoutTimer);
// Attempt to subscribe to the supplied list of addresses.
foreach (var address in addressCollection)
{
SubscriberSocket socket = new SubscriberSocket();
socketCollection.Add(socket);
//socket.ReceiveReady -= messageHandler;
socket.ReceiveReady += messageHandler;
tmpPoller.Add(socket);
// Subscribe to welcome messages.
socket.Subscribe(WELCOME_MESSAGE);
socket.Connect(address);
}
tmpPoller.Run(); // Block and wait for connection.
// We should have an active socket/conection.
if (connectedSocket != null)
{
// Remove the connected socket from the collection.
socketCollection.Remove(connectedSocket);
ZeroMqHelpers.CloseConnectionsImmediately(socketCollection);
// Set the active socket.
subscriber = connectedSocket;
//subscriber.SkipMultipartMessage(); // This skips the welcome message.
// Subscribe to subscriptions.
subscriber.Subscribe(HEARTBEAT_MESSAGE);
foreach (var subscription in subscriptions)
subscriber.Subscribe(subscription);
// Remove start-up handler, now handle messages properly.
subscriber.ReceiveReady -= messageHandler;
subscriber.ReceiveReady += OnSubscriberReceiveReady;
poller.Add(subscriber);
// Reset timers.
timeoutTimer.Enable = true;
reconnectionTimer.Enable = false;
}
else // We need to attempt re-connection.
{
// Close all existing connections.
ZeroMqHelpers.CloseConnectionsImmediately(socketCollection);
timeoutTimer.Enable = false;
reconnectionTimer.Enable = true;
}
}
}
private void OnShimReceiveReady(object sender, NetMQSocketEventArgs e)
{
string command = e.Socket.ReceiveFrameString();
if (command == NetMQActor.EndShimMessage)
{
poller.Stop();
}
else if (command == SUBSCRIBE_COMMAND)
{
string topic = e.Socket.ReceiveFrameString();
subscriptions.Add(topic);
if (subscriber != null)
subscriber.Subscribe(topic);
}
}
private void OnTimeoutTimerElapsed(object sender, NetMQTimerEventArgs e)
{
if (subscriber != null)
{
poller.Remove(subscriber);
subscriber.Dispose();
subscriber = null;
Connect();
}
}
private void OnReconnectionTimerElapsed(object sender, NetMQTimerEventArgs e)
{
// We re-attempt connection.
Connect();
}
private void OnSubscriberReceiveReady(object sender, NetMQSocketEventArgs e)
{
// Here we just forwward the message on to the actor.
var message = subscriber.ReceiveMultipartMessage();
string topic = message[0].ConvertToString();
// Let us see what is in the message.
if (message.Count() > 1)
{
string content = message[1].ConvertToString();
Console.WriteLine($"ZMQ_ALT - {topic}:: {content}");
}
if (topic == WELCOME_MESSAGE)
{
// Disconnection has occurred we might want to restore state from a snapshot.
}
else if (topic == HEARTBEAT_MESSAGE)
{
// We got a heartbeat, lets postponed the timer.
timeoutTimer.Enable = false;
timeoutTimer.Enable = true;
}
else
{
shim.SendMultipartMessage(message);
}
}
public void Subscribe(string topic)
{
actor.SendMoreFrame(SUBSCRIBE_COMMAND).SendFrame(topic);
}
public NetMQMessage ReceiveMessage()
{
return actor.ReceiveMultipartMessage();
}
public void PublishMessage(NetMQMessage message)
{
actor.SendMoreFrame(PUBLISH_MESSAGE_TOPIC)
.SendMultipartMessage(message);
}
private bool disposedValue = false;
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
actor?.Dispose();
subscriber?.Dispose();
shim?.Dispose();
poller?.Dispose();
}
disposedValue = true;
}
}
public void Dispose()
{
Dispose(true);
}
}
}
Now, I can send messages from the server to the client which is awesome and the client using the following code from the main method in two separate console applications
Program.cs for SERVER:
class Program
{
static void Main(string[] args)
{
using (ZeroMqMessageServer server = new ZeroMqMessageServer("tcp://127.0.0.1:6669"))
{
while (true)
{
NetMQMessage message = new NetMQMessage();
message.Append("A");
message.Append(new Random().Next().ToString());
server.PublishMessage(message);
Thread.Sleep(200);
}
}
}
}
Program.cs for CLIENT:
class Program
{
static void Main(string[] args)
{
Task.Run(() =>
{
using (ZeroMqMessageClient client = new ZeroMqMessageClient("tcp://127.0.0.1:6669"))
{
client.Subscribe(String.Empty);
while (true) { }
}
});
Console.ReadLine();
}
}
The client correctly auto-detects dropped connections and reconnects, fantastic little pattern.
However, this pattern out-of-the-box does not allow the client to send messages to the server. So in the client I have added the following code
public void PublishMessage(NetMQMessage message)
{
actor.SendMoreFrame(PUBLISH_MESSAGE_TOPIC)
.SendMultipartMessage(message);
}
and in the client I have changed the publisher.ReceiveReady += DropPublisherSubscriptions; event handler to
private void DropPublisherSubscriptions(object sender, NetMQSocketEventArgs e)
{
var message = e.Socket.ReceiveMultipartMessage();
string topic = message[0].ConvertToString();
Console.WriteLine($"TOPIC = {topic}");
// Let us see what is in the message.
if (message.Count() > 1)
{
string content = message[1].ConvertToString();
Console.WriteLine($"TEST RECIEVE FROM CLIENT - {topic}:: {content}");
}
publisher.SkipMultipartMessage();
}
but this does not seem to handle my messages. It receives the heartbeats and welcome messages, but I am not doing this right.
How can I enable/facilitate the client to talk to the server without breaking what I have already?
Thanks for your time.

Storing the connection id of a specific client in SignalR hub

Below you can see a simplified version of my SignalR self hosted hub on a windows service:
public static class SubscriptionHandler
{
public static int PriceFeedMembersCount = 0;
}
public class PriceHub : Hub
{
public Task SubscribeToPriceFeed()
{
IHubContext context = GlobalHost.ConnectionManager.GetHubContext<PriceHub>();
if (SubscriptionHandler.PriceFeedMembersCount == 0)
{
context.Clients.All.updatePriceSubscriptionStatus(true);
}
SubscriptionHandler.PriceFeedMembersCount++;
return context.Groups.Add(Context.ConnectionId, "PriceFeed");
}
public Task UnsubscribeFromPriceFeed()
{
IHubContext context = GlobalHost.ConnectionManager.GetHubContext<PriceHub>();
SubscriptionHandler.PriceFeedMembersCount--;
if (SubscriptionHandler.PriceFeedMembersCount == 0)
{
context.Clients.All.updatePriceSubscriptionStatus(false);
}
return context.Groups.Remove(Context.ConnectionId, "PriceFeed");
}
public void NotifySubscribers(Price price)
{
IHubContext context = GlobalHost.ConnectionManager.GetHubContext<PriceHub>();
context.Clients.Group("PriceFeed").updatePrice(price);
}
}
And I have two types of clients for that hub: One of them is web applications and the other one is windows services. Here you can see a demo implementation for my windows service as a signalr client:
public partial class WinSer45 : ServiceBase
{
private HubConnection hubConnection;
private IHubProxy priceProxy;
private Timer timer = new Timer();
private bool hasSubscribers = false;
public WinSer45()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
timer.Interval = 1000; // saniyede bir
timer.Elapsed += timer_Elapsed;
timer.Enabled = true;
hubConnection = new HubConnection("http://localhost:8080/signalr", useDefaultUrl: false);
priceProxy = hubConnection.CreateHubProxy("PriceHub");
hubConnection.Start().Wait();
priceProxy.On<bool>("UpdatePriceSubscriptionStatus", hasSubscribers =>
{
this.hasSubscribers = hasSubscribers;
});
}
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
if (hasSubscribers)
{
TestPrice testPrice = new TestPrice() { Id = 1, Buy = 1.2345, Sell = 9.8765, Symbol = "EURUSD" };
priceProxy.Invoke("NotifySubscribers", testPrice).Wait();
}
}
protected override void OnStop()
{
}
}
As you see I use the hasSubscribers flag to minimize the messages between hub and clients. And hasSubscribers flag is changed by SubscribeToPriceFeed and UnsubscribeFromPriceFeed methods.
If you look carefully you see the line below in SubscribeToPriceFeed:
context.Clients.All.updatePriceSubscriptionStatus(true);
I don't want to send the message to all clients but my client windows service. How can I store the connection Id of a specific client in my hub? If I can do that, I know I can send message to a specific connectionId as in the line below:
context.Clients.Client(connectionId).updatePriceSubscriptionStatus(true);
Thanks in advance,
pass source during connection
like this
hubConnection = new HubConnection("http://localhost:8080/signalr","source=windows",useDefaultUrl: false);
HUB
public override Task OnConnected()
{
var source= Context.QueryString['source'];
return base.OnConnected();
}
create a class which will hold the user with source
public class user {
public string ConnectionID {set;get;}
public string Source {set;get;}
}
declare a list in the hub
List<user> userList=new List<user>();
Then push the user during OnConnected
public override Task OnConnected()
{
var us=new user();
us.Source = Context.QueryString['source'];
us.ConnectionID=Context.ConnectionId;
userList.Add(us);
return base.OnConnected();
}
and during broadcast just filter it by source
var windowsUser=userList.Where(o=>o.Source == "windows").ToList(); // you'll get the windows user list

event - object referance is not set to an instanse of an object windows forms C#

I am trying to raise an event in a DLL file refrenced to a windows forms project.
I have the following message when I run the program "Object is not set to an instace of an object":
namespace Server
{
public delegate void messageHnadler();
public class ClassServer
{
public event messageHnadler messageForChat
public string Message { get; set; }
public Socket listenerSocket;
public BinaryFormatter transBinary;
public Thread threadingServer;
public TcpListener listenerServer;
private List<TcpClient> connectedClients = new List<TcpClient>();
public bool OpenServer(string ipAddress, int PortNumber)
{
try
{
listenerServer = new TcpListener(IPAddress.Parse(ipAddress), PortNumber);//creating listener for clients to connect
listenerServer.Start();
threadingServer = new Thread(LoopThroughClients);
threadingServer.Start();
threadingServer = new Thread(GetMessage);
threadingServer.Start();
return true;
}
catch (Exception)
{
return false;
}
}
public void LoopThroughClients()
{
listenerSocket = listenerServer.AcceptSocket();
}
public void GetMessage()
{
while (true)
{
if (listenerSocket != null)
{
NetworkStream streamWithClient = new NetworkStream(listenerSocket);
transBinary = new BinaryFormatter();
string stringFromClient = (string)transBinary.Deserialize(streamWithClient);
if (stringFromClient != null)
{
Message = stringFromClient;
messageForChat();
}
streamWithClient = new NetworkStream(listenerSocket);
BinaryFormatter tranBinary = new BinaryFormatter();
tranBinary.Serialize(streamWithClient, stringFromClient);
stringFromClient = null;
}
}
}
In the windows forms project I signed the event to a function:
namespace Chat_Project_Server_UI
{
public partial class SeverUI : Form
{
OpenServerForm openServer = new OpenServerForm();
ClassServer serverForEvent = new ClassServer();
public SeverUI()
{
InitializeComponent();
openServer.ShowDialog();
serverForEvent.messageForChat += new messageHnadler(serverForEvent_messageForChat);
OpenningServer();
}
public void OpenningServer()
{
if(openServer.IsConnected)
{
ChatTextBox.AppendText("SERVER OPEN!\n");
}
else
{
ChatTextBox.AppendText("Faild to open server...\n");
}
}
private void test_Click(object sender, EventArgs e)
{
ChatTextBox.AppendText("aaaaa");
}
public void EventHolder()
{
}
void serverForEvent_messageForChat()
{
ChatTextBox.AppendText(serverForEvent.Message);
}
}
Always check if a handler has been assigned first as follows:
var handler = messageForChat;
if (handler != null)
handler()
Standard Way to handle Events inside the Class that defines it Is to Create A Method Named OnXxx and Always Check whether the Event is Assigned Handler Or Not
in your case define new function as following:
protected void OnMessageForChat(){
//protected modifier allows subclasses to raise the event by calling this method
if (messageForChat!=null)messageForChat();
}
And WhenEver you want to raise the event Just Call this Function

Categories

Resources