Using this C# TCP Server example within a Unity project
https://www.codeproject.com/articles/488668/csharp-tcp-server
The notes mention There are 3 callback events OnConnect, OnDataAvailable and OnError.
There are 2 callback examples with the following signatures
private void tcpServer1_OnDataAvailable(tcpServer.TcpServerConnection connection)
Do I need to do anything special or in addition to enable these callbacks or is tcpServer1_OnDataAvailable consdiered a reserved handler name that is automatically called?
TcpServer tcpServer1 = new TcpServer(); //in constructor (auto added if added as a component)
private void openTcpPort(int port)
{
tcpServer1.Port = port;
tcpServer1.Open();
}
private void closeTcpPort()
{
tcpServer1.Close();
}
You'll need to register the event handlers delegates to the specific events.
TcpServer tcpServer1 = new TcpServer();
// register event handler
tcpServer1.OnDataAvailable += tcpServer1_OnDataAvailable;
private void tcpServer1_OnDataAvailable(tcpServer.TcpServerConnection connection)
{
// do work
}
Callbacks are methods that are called when an event you are interested in occurs. You do in fact need to set them up, like this:
tcpServer1.OnConnect += serverConnection =>
{
//code to do stuff when a connection happens goes here
}
tcpServer1.OnDataAvailable += serverConnection =>
{
//code to do stuff when data is available here
}
tcpServer1.OnError += serverConnection =>
{
//code to do stuff when an error happens here
}
You should put this code in the constructor, after the point in time when tcpServer1's variable is instantiated with operator new.
Related
I'm working on a software where software issues commands for hardware panel and once a command is issued, its response received after few seconds . there are different functions for different hardware commands like
public void FunctionA()
{
StartCommandA();
}
and other functions on the same pattern that will be used to run other commands.
FunctionB();
FunctionC();
Once we receive the response of command A , I invoke the other function from the response but this approach is not good as per design pattern practices.
All i want to do is to make a list of functions and invoke all these functions one after other, But next function will be called once i get response of first functions.
I tried this by using Multicast delegate but I'm unable to find out how we can call get the list of functions once i add all functions to that delegates. This is what i'm trying do since.
FunList funList_ConfigAndSerialTests = new FunList(StartSerialTest);
funList_ConfigAndSerialTests += StartSerialTest;
funList_ConfigAndSerialTests += StartMsrTest;
funList_ConfigAndSerialTests += StartContactLessTest;
//funList_ConfigAndSerialTests.Invoke();
Delegate[] del = funList_ConfigAndSerialTests.GetInvocationList();
foreach (Delegate item in funList_ConfigAndSerialTests.GetInvocationList())
{
while (true)
{
if (IsResponseReceived == true)
{
// Call function here
}
}
}
The simplest way to do this is to call the functions one by one:
FunctionA();
FunctionB();
FunctionC();
Each method will be called only after the previous has returned.
But you said you want to call the next function after the previous one has a response. Now that sounds like your functions run asynchronously. I strongly suggest you use the async keyword to mark your functions and make them return a Task<ResonseType>. You can learn about this here.
You'll then be able to do something like this:
await FunctionA(); // you obviously want to do something with the returned response
// I do not know your requirements so I did not show that part
await FunctionB();
await FunctionC();
It seems what you're trying to achieve is what Events are for. In the class, where the handlers (FunctionA, FunctionB, ...) are defined create an event instance as follows:
public class MyClass
{
private event Action Event;
public void RegisterHandlers()
{
Event += FuncA;
Event += FuncB;
Event();
}
public void HandleCommand()
{
this.Event();
}
private void FuncA() { /*...*/ }
private void FuncB() { /*...*/ }
}
The simple call to Events() will actually result in all the registered handlers to be invoked in the order they've been registered.
Sorry for the title, i didn't find it easy to resume.
My issue is that I need to implement a c# dll that implements a 'scan' method, but this scan, when invoked, must not block the main thread of the application using the dll. Moreover, it is a duty that after the scan resolves it rises an Event.
So my issue (in the deep) is that i'm not so experienced at c#, and after very hard investigation i've come up with some solutions but i'm not very sure if they are the "right" procedures.
In the dll i've come up with:
public class Reader
{
public delegate void ReaderEventHandler(Object sender, AlertEventArgs e);
public void Scan(String ReaderName)
{
AlertEventArgs alertEventArgs = new AlertEventArgs();
alertEventArgs.uuiData = null;
//Code with blocking scan function here
if (ScanFinnished)
{
alertEventArgs.uuiData = "Scan Finnished!";
}
alertEventArgs.cardStateData = readerState[0].eventState;
ReaderEvent(new object(), alertEventArgs);
}
public event ReaderEventHandler ReaderEvent;
}
public class AlertEventArgs : EventArgs
{
#region AlertEventArgs Properties
private string _uui = null;
private uint cardState = 0;
#endregion
#region Get/Set Properties
public string uuiData
{
get { return _uui; }
set { _uui = value; }
}
public uint cardStateData
{
get { return cardState; }
set { cardState = value; }
}
#endregion
}
While in the main app I do:
Reader reader;
Task polling;
String SelectedReader = "Some_Reader";
private void bButton_Click(object sender, EventArgs e)
{
reader = new Reader();
reader.ReaderEvent += new Reader.ReaderEventHandler(reader_EventChanged);
polling = Task.Factory.StartNew(() => reader.Scan(SelectedReader));
}
void reader_EventChanged(object sender, AlertEventArgs e)
{
MessageBox.Show(e.uuiData + " Estado: " + e.cardStateData.ToString("X"));
reader.Dispose();
}
So here, it works fine but i don't know if it's the proper way, in addition i'm not able to handle possible Exceptions generated in the dll.
Also tried to use async/await but found it difficult and as I understand it's just a simpler workaround Tasks.
What are the inconvinients of this solution? how can i capture Exceptions (are they in other threads and that's why i cant try/catch them)? Possible concept faults?
When your class sends events, the sender usually is that class, this. Having new object() as sender makes absolutely no sense. Even null would be better but... just use this.
You shouldn't directly raise events as it might result in race conditions. Might not happen easily in your case but it's just a good guideline to follow. So instead of calling ReaderEvent(new object(), alertEventArgs); call RaiseReaderEvent(alertEventArgs); and create method for it.
For example:
private void RaiseReaderEvent(AlertEventArgs args)
{
var myEvent = ReaderEvent; // This prevents race conditions
if (myEvent != null) // remember to check that someone actually subscribes your event
myEvent(this, args); // Sender should be *this*, not some "new object()".
}
Though I personally like a bit more generic approach:
private void Raise<T>(EventHandler<T> oEvent, T args) where T : EventArgs
{
var eventInstance = oEvent;
if (eventInstance != null)
eventInstance(this, args);
}
Which can then be used to raise all events in same class like this:
Raise(ReaderEvent, alertEventArgs);
Since your scan should be non-blocking, you could use tasks, async/await or threads for example. You have chosen Tasks which is perfectly fine.
In every case you must understand that when you are not blocking your application, your application's main thread continues going like a train. Once you jump out of that train, you can't return. You probably should declare a new event "ErrorEvent" that is raised if your scan-procedure catches an exception. Your main application can then subscribe to that event as well, but you still must realize that those events are not (necessarily) coming from the main thread. When not, you won't be able to interact with your GUI directly (I'm assuming you have one due to button click handler). If you are using WinForms, you'll have to invoke all GUI changes when required.
So your UI-thread safe event handler should be something like this:
void reader_EventChanged(object sender, AlertEventArgs e)
{
if (InvokeRequired) // This true for others than UI Thread.
{
Invoke((MethodInvoker)delegate
{
Text = "My new title!";
});
}
else
Text = "My new title!";
}
In WPF there's Dispather that handles similar invoking.
I'm quite new to C# and certainly OOP concepts.. so forgive the stupidity of my question.
I have a system I wish to communicate with, It has a number of commands that can be called with an associated response. (Communication is done via TCP/IP or Serial) (I implemented an Interface with SendMessage so that I can use multiple transport mechanisms)
I want to create a method for each command and then expose these, which is simple enough. The device also lets say 'broadcasts' messages as well which I want to act on, so I was using an event handler for this which works well..
At the moment in the event handler I catch OK and ERROR style messages, but ideally I would like to also be able to send the command from the above method and catch an error and return a bool value based on the command.
Can anyone think of a way I can do something like this and point me in the right direction?
Thanks
David
You can use helper to wait for event. Some ugly code from past:
public class ComWait
{
ManualResetEvent _waitEvent;
SomeEvent _eventHandler;
public ComWait()
{
_waitEvent = new ManualResetEvent(false);
_eventHandler = new SomeEvent(Watch);
}
void Watch()
{
_waitEvent.Set();
}
public bool Wait(int time = 3000)
{
_waitEvent.Reset();
SomeEvent += _eventHandler;
bool result = _waitEvent.WaitOne(time, false);
SomeEvent -= _eventHandler;
return result;
}
}
Usage is
ComWait wait = new ComWait();
if(!wait.Wait())
return; // timeout
// process
It will simply block synchronous method until event is rised or timeout occurs. It should be easy to add parameters: to unblock on specific event and to pass event handler parameters back to caller.
Otherwise I would simply have method inside communication class to use as a blocker:
readonly object _waitLock = new object();
public void Wait()
{
lock (_waitLock)
if (!Monitor.Wait(_waitLock, 3000))
throw new TimeoutException("No communications");
}
Signal at same time as you rise event:
lock (_waitLock)
Monitor.PulseAll(_waitLock);
For multiple instances, when event handlers are declared like below, do they tend to overlap and set all the instances of a variables
For say,
Something class = new Something();
is declared ~ 3 times and on all 3 times, the eventhandlers are declared and used.
public class something
{
public string str = "1";
public string str2 = "2";
public void onconnect(object sender, ConnectedEventArgs e)
{
if (e.Connected)
{
this.ses = e.NetworkSession;
this.ses.OnHandshakeHandler += new EventHandler<HSEventArgs>(OnHandshakeHandler);
this.ses.onreceive+= new EventHandler<PEventArgs>(onreceive);
return;
}
}
}
now lets say
public void onreceive(object sender, PEventArgs e)
{
str = "3";
}
Would str all be turned to "3" onrecieve? Because in my case, i'm starting to believe the eventhandler is shared between all instances of the class. Therefore rendering all variables in all instances of the class to be the same.
If this is not the case, could eventhandlers be the reason behind why my variables are all getting changed by the same event raised?
If so, how would you isolate the class and assign the handler to each individual class?
onconnect is called by
public void Connect(string ip, short port)
{
try
{
this.connector = new Connector();
this.connector.OnClientConnected += new EventHandler<ConnectedEventArgs>(onConnect);
this.connector.Connect(ip, port); //Logs into server
}
catch
{
updateLog("[Error]Servers exploded!!!", this);
}
}
and ^ is called when a button is pushed on a gui
If I read the documentation correctly (http://msdn.microsoft.com/en-us/library/bb975820.aspx) there will be one NetworkSession per user. You are one user, so you have one NetworkSession.
You created three instances of Something, and I get the feeling they are all called by the same event: the software os connected to the game network.
All 3 onconnect methods get in e the same instance of NetworkSession and you connect your eventhanlder onreceive to NetworkSession.onreceive.
So if the NetworkSession receives something, all the 3 eventhandlers of your 3 instances are called.
The creating a seperate NetworkSession per instance by using NetworkSession.BeginCreate (http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.net.networksession.begincreate.aspx).
At the moment I am in the process of building a custom button handler (I needed to integrate the kinect into the button system which also used a mouse) then I got to a horrible thing called Event Handling.. at least an hour yelling at my pc :P. I was wondering, before I go and spend a while changing my system to allow for my new want, which is to have multiple events per handler, I was wondering, is the way I'm going to try work (I would just try, but I'm getting off for the night, so my hope is that I can save some time when I boot the computer up tomorrow and not attempt if my system isn't designed for it)
Also, ive seen a getInvoc list or somthing like that before when I was coding.. Would I add multiple delegates onto it then get that list and itterate over it?
On previous examples I had seen where people used:
public event EventHandler myEventHandler;
I had to use:
private Dictionary<BtnEvent, Delegate> m_events;
and then they did the following to add a handler (their way, not mine):
myObj.myEventHandler += delegate(object sender, EventArgs ea)
{
//do stuff on event
};
first.. If they ran this twice, once with funcA and second with funcb would it run both? or just one?
second, if I applied that logic of += to a Delegate would it work? (I had to use Delegate as I was storing the handlers inside of a dictionary, this allowed for logical access to handlers through use of an enum)
(my code)
private Dictionary<BtnEvent, Delegate> m_events;
//....
m_events = new Dictionary<BtnEvent, Delegate>(6);
m_events.Add(BtnEvent.CLICK_ENTER, null);
m_events.Add(BtnEvent.CLICK_LEAVE, null);
m_events.Add(BtnEvent.CLICK_STAY, null);
m_events.Add(BtnEvent.HOVER_ENTER, null);
m_events.Add(BtnEvent.HOVER_LEAVE, null);
m_events.Add(BtnEvent.HOVER_STAY, null);
//....
public bool addHandle(BtnEvent stateToGet, Delegate function)
{
bool success = false;
if(m_events.ContainsKey(stateToGet))
{
m_events[stateToGet] = function;
}
return(success);
}
// CHANGE ABOVE TO:
public bool addHandle(BtnEvent stateToGet, Delegate function)
{
bool success = false;
if(m_events.ContainsKey(stateToGet))
{
m_events[stateToGet] += function;
}
return(success);
}
Will changing m_events[stateToGet] = function; to m_events[stateToGet] += function; allow me to have multiple event handles (functions I passed to addHandle) be called through the following code?
private void ExecuteEvent(BtnEvent currEvent)
{
if(m_events.ContainsKey(currEvent))
{
if(m_events[currEvent] != null)
{
m_events[currEvent].DynamicInvoke(null);
}
}
}
Please see below code which answers your first question:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.Load += new EventHandler(Form1_Load);
}
void Form1_Load(object sender, EventArgs e)
{
funcA();
funcB();
}
private void funcA()
{
button1.Click += new EventHandler(button1_Click);
}
private void funcB()
{
button1.Click += new EventHandler(button1_Click);
}
void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("I am in event handler");
}
}
On clicking the Button, "I am in event handler" message is shown twice which means += operator works in similar way with delegates as it works with integers or strings. It simply adds the function handler to the queue and upon execution of events, calls all the function pointers in queue.
Regarding your second question, I think you wont achieve the expected behavior by changing = to +=. What I understand from your statement is that, you wish to execute multiple events handlers like CLICK_ENTER, CLICK_LEAVE on calling ExecuteEvent() function. However, since you are storing event handlers and their delegates in a Dictionary, changing = to += will only work in the same way as illustrated in above code.