I'm trying to port my code from an obsolete library called CastleMQ to NetMQ but I'm running into some problems.
I prefer to using polling with a timeout, for reliability - I just found that it worked best for me from trial and error compared to just sitting blocking the port indefinitely.
here is my CastleMQ code
public int ZeroPort;
private void ThreadProc()
{
var ctx = new Context();
try {
using (var repSocket = ctx.CreateSocket(SocketType.Rep))
{
string bindAddress = "tcp://*:"+ZeroPort;
repSocket.Bind(bindAddress);
print2("*** BINDING on {0} ***", bindAddress);
bool quit = false;
while (!quit) {
try {
var polling = new Polling(PollingEvents.RecvReady, repSocket);
polling.RecvReady += (socket) =>
{ // using socket.Recv() here is guaranted to return stuff
var msg = socket.Recv();
var msgStr = Encoding.UTF8.GetString(msg);
print2("[REP:{0}] {1}", bindAddress, msgStr);
switch (msgStr) {
case "positions": {
StringBuilder csv = new StringBuilder();
print2("csv: {0}", csv.ToString());
socket.Send(csv.ToString());
break;
}
default: {
socket.Send("Unrecognized Command: " + msgStr);
break;
}
}
};
polling.Poll(POLL_TIMEOUT_MS); // this returns once some socket event happens
} catch (Exception e) {
if (e is ThreadAbortException) {
quit = true;
print2("\n*** EXITED ***");
} else print2(e.ToString());
}
}
}
} catch (Exception e) {
print2(e.ToString());
} finally {
ctx.Dispose();
}
}
here is what I tried to do and then got lost with NetMQ
private void ThreadProc()
{
try {
string bindAddress = "#tcp://*:" + ZeroPort;
print2("*** BINDING on {0} ***", bindAddress);
using (var repSocket = new ResponseSocket(bindAddress))
using (var poller = new NetMQPoller { repSocket })
{
// bool quit = false;
// while (!quit)
// these event will be raised by the Poller
repSocket.ReceiveReady += (s, a) =>
{
// receive won't block as a message is ready
string msg = a.Socket.ReceiveString(); // defeinition for ReceiveString() can't be found
// send a response
a.Socket.Send("Response"); // it doesn't like "Response", do I need to wrap it in some object?
I'm especially confused as how to add a timeout so I can poll with a timeout in a loop the way my CastleMQ code does.
Any pointers would be much appreciated, thanks
Related
I have an async function which still freezes / lags the UI thread for me when I execute it. This is my function calling it.
private void TcpListenerLogic(object sender, string e)
{
Application.Current.Dispatcher.BeginInvoke((Action)async delegate {
try
{
dynamic results = JsonConvert.DeserializeObject<dynamic>(e);
if (results.test_id != null)
{
// Get properties for new anchor
string testInformation = await CommunicationCommands.getJsonFromURL(
"http://" + ServerIP + ":" + ServerPort + "/api/" + results.test_id);
}
}
catch (Exception exception)
{
// Writing some Trace.WriteLine()'s
}
});
}
And this is the async function that freezes my UI Thread
public static async Task<string> getJsonFromURL(string url)
{
try
{
string returnString = null;
using (System.Net.WebClient client = new System.Net.WebClient())
{
returnString = await client.DownloadStringTaskAsync(url);
}
return returnString;
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
return null;
}
}
I already tried to make everything in TcpListenerLogic run in a new Thread:
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
}).Start();
Which resulted in the whole UI completely freezing. And I tried to make TcpListenerLogic async and await the dispatcher, which also made everything freeze permanently. I also tried to make TcpListenerLogic async and leave the dispatcher. The dispatcher is only there because I normally have some UI code in there, which I left out for my tests.
I have ventured far through the internet, but no BackgroundWorker, ThreadPool or other methods helped me in my endeavour.
If anyone has help for this particular problem, or a resource that would improve my understanding of async functions in C#, I would much appreciate it.
Edit
As requested a deeper insight in how this event handler is called.
I have System.Net.Websocket, which is connected to the Backend API I am working with and triggers an event, everytime he receives new Data. To guarantee the socket listens as longs as it is open, there is a while loop which checks for the client state:
public event EventHandler<string> TcpReceived;
public async void StartListener(string ip, int port, string path)
{
try
{
using (client = new ClientWebSocket())
{
try
{ // Connect to backend
Uri serverUri = new Uri("ws://" + ip + ":" + port.ToString() + path );
await client.ConnectAsync(serverUri, CancellationToken.None);
}
catch (Exception ex)
{
BackendSettings.IsConnected = false;
Debug.WriteLine("Error connecting TCP Socket: " + ex.ToString());
}
state = client.State;
// Grab packages send in backend
while (client.State == WebSocketState.Open || client.State == WebSocketState.CloseSent)
{
try
{
// **Just formatting the received data until here and writing it into the "message" variable**//
TcpReceived(this, message);
// Close connection on command
if (result.MessageType == WebSocketMessageType.Close)
{
Debug.WriteLine("Closing TCP Socket.");
shouldstayclosed = true;
await client.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
break;
}
state = client.State;
}
catch
{
BackendSettings.IsConnected = false;
state = client.State;
}
}
state = client.State;
}
}
catch (Exception ex)
{
// Some error messages and settings handling
}
}
The Event has a handler attached:
TcpReceived += TcpListener_TcpReceived;
And this is the Handler, which calls the previously seen "TcpListenereLogic".
private void TcpListener_TcpReceived(object sender, string e)
{
TcpListenerLogic(sender, e);
//App.Current.Dispatcher.BeginInvoke(new Action(() => {
// TcpListenerLogic(sender, e);
//}));
//new Thread(() =>
//{
// Thread.CurrentThread.IsBackground = true;
// TcpListenerLogic(sender, e);
//}).Start();
}
I previously had the "TcpListenereLogic" as the handler, but I wanted to try different methods to call it. I also left in the commented out part, to show how the call of "TcpListenereLogic" looked already. All my attempts were with all mentioned setups and sadly lead to nothing.
Thank you very much #TheodorZoulias for helping me to find the solution to my problem.
It turns out it wasn't the async function itself, but rather how often it gets called. It got called roughly ~120 times every second.
My solution starts by calling the Listener method over a new Thread:
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
MainWindow.tcpListener.StartListener(ip, portNumber, "/api/");
}).Start();
To limit the amount of calls that happen every second I added a dispatcher timer, that resets a bool after it has been used for a call, by my Event.
readonly System.Windows.Threading.DispatcherTimer packageIntervallTimer =
new System.Windows.Threading.DispatcherTimer();
bool readyForNewPackage = true;
private void ReadyForPackage(object sender, EventArgs e)
{
readyForNewPackage = true;
}
public async void StartListener(string ip, int port, string path)
{
packageIntervallTimer.Interval = TimeSpan.FromMilliseconds(50);
packageIntervallTimer.Tick += (s, e) => { Task.Run(() => ReadyForPackage(s, e)); };
packageIntervallTimer.Start();
Then I wrapped everything inside the while loop into an if condition based on the bool, the most important part was to have my "event EventHandler TcpReceived" in there:
// Grab packages sent in backend
while (client.State == WebSocketState.Open || client.State == WebSocketState.CloseSent)
{
if (readyForNewPackage == true)
{
readyForNewPackage = false;
try
{
....
TcpReceived(this, message);
....
}
catch
{
...
}
}
}
I added my TcpListenerLogic to the Eventhandler:
TcpReceived += TcpListenerLogic;
And my TcpListenerLogic now looked like this (names have been changed):
private async void TcpListenerLogic(object sender, string e)
{
try
{
dynamic results = JsonConvert.DeserializeObject<dynamic>(e);
if (results.test_id != null)
{
string testID = "";
if (results.test_id is JValue jValueTestId)
{
testID = jValueTestId.Value.ToString();
}
else if (results.test_id is string)
{
testID = results.test_id;
}
// Get properties for new object
string information = await CommunicationCommands.getJsonFromURL(
"http://" + ServerIP + ":" + ServerPort + "/api/" + testID );
if (information != null)
{
await App.Current.Dispatcher.BeginInvoke(new Action(() =>
{
// Create object out of the json string
TestStatus testStatus = new TestStatus();
testStatus.Deserialize(information);
if (CommunicationCommands.isNameAlreadyInCollection(testStatus.name) == false)
{
// Add new object to the list
CommunicationCommands.allFoundTests.Add(testStatus);
}
}));
{
}
catch (Exception exception)
{
....
}
}
Adding a new Thread to execute any step results in problems, so keep in mind that all this uses the thread created at the beginning for "StartListener"
I connect to my (C#) server and from an App built in Corona SDK but for the second person can never connect.
I have tried using different IP's i.e. two cellphones with external IP's with no difference.
This is how my server listener works:
server.cs
void Listener()
{
while (isRunning)
{
try
{
Socket socket = listener.AcceptSocket();
foreach (var worker in workers)
if (worker.IsAvailable)
{
worker.ProcessNewSocket(socket);
break;
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
public void Run()
{
Console.WriteLine("Server.Run()");
listener.Start();
isRunning = true;
foreach (var worker in workers)
{
Thread t = new Thread(worker.Run);
t.Start();
}
Listener();
}
ServerWorker.cs
public void ProcessNewSocket(Socket socket)
{
var pc = new PlayerClient(this);
sockets.Add(socket, pc);
}
// this method will be called in cycle
public void Run()
{
while (server.IsRunning)
{
List<Socket> readList = sockets.Keys.ToList(); //List of sockets that have some data from client available for reading.
List<Socket> writeList = sockets.Keys.ToList(); //List of sockets that are ready to write (send) to the client. An action was made to a table and the change was sent to PlayerClient.Write and is now stored in the queue (MemoreStream)
List<Socket> errorList = sockets.Keys.ToList();
if (readList.Count() != 0 || writeList.Count() != 0 || errorList.Count() != 0)
{
// for providing security you can use System.Net.Security.SslStream here when read/write data,
// see http://msdn.microsoft.com/ru-ru/library/system.net.security.sslstream(v=vs.110).aspx
Socket currentSocket = null;
// foreach socket with events
try
{
foreach (var s in readList)
{
currentSocket = s;
//TODO: Get the actual length of the message.
byte[] data = new byte[2048];
s.Receive(data);
sockets[s].OnData(data);
}
foreach (var s in writeList)
{
currentSocket = s;
if (sockets[s].IsWriteDataAvailable())
{
s.Send(sockets[s].GetWriteBuffer());
sockets[s].ClearWriteBuffer();
}
}
foreach (var s in errorList)
{
//OnError
}
}
// we got exception, depending on the type...
catch (SocketException ex)
{
//Console.WriteLine(ex.ToString());
// send client error message, this is not always possible(for example network failure)
// maybe we would like to notify his opponent about connection failure
// terminate connection
if (ex.ErrorCode == (int)SocketError.ConnectionAborted || ex.ErrorCode == (int)SocketError.ConnectionReset)
RemoveSocket(currentSocket);
else
Console.WriteLine("Other problem .. " + ex.ErrorCode.ToString());
}
}
}
}
I'm new in network programming so I'm not really sure what to do. I have read about using ASync but first I would like to know if there is something I can do with this code and/or if I should change it completely?
I think the "BREAK" statement in your Listener() Block;
foreach (var worker in workers)
if (worker.IsAvailable)
{
worker.ProcessNewSocket(socket);
break; // this BREAK WILL END YOUR loop AFTER first CLIENT FOUND.
}
So, try removing break as;
foreach (var worker in workers)
{
if (worker.IsAvailable)
{
worker.ProcessNewSocket(socket);
}
}
I wrote a service to send sensor data over bluetooth on android. Although I got no errors my C# client stops getting data after I sent exactly 561K data. At this moment it seems like my android continues to send data but my client doesn't get any. After a while, android also stops sending data. I tried different configurations. My program always stops sending data after "Service->Server". I don't get any errors but it stops sending. Here is android program.
#Override
public synchronized int onStartCommand(Intent intent, int flags, int startId) {
Log.i(EXTRA_MESSAGE,"onStartCommand");
if(isRunning)
Log.e(EXTRA_MESSAGE, "I am already running");
else
{
isRunning = true;
BluetoothDevice selectedDevice = (BluetoothDevice) intent.getParcelableExtra(EXTRA_MESSAGE);
if(selectedDevice == null)
{Log.i(EXTRA_MESSAGE,"null it is "); return -1;}
connect = new ConnectThread(selectedDevice);
connect.start();
mHandler =new Handler(){
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch(msg.what){
case SUCCESS_CONNECT:
connected = new ConnectedThread((BluetoothSocket) msg.obj);
Toast.makeText(getApplicationContext(), "Connected", 0).show();
//connected.write(("Connected").getBytes());
Log.i(EXTRA_MESSAGE, "we are connected");
isConnected = true;
break;
case MESSAGE_READ:
Toast.makeText(getApplicationContext(), ((byte[]) msg.obj).toString(), 0).show();
break;
}
}
};
mSensor = (SensorManager) getSystemService(SENSOR_SERVICE);
sSensor = mSensor.getDefaultSensor(Sensor.TYPE_ORIENTATION);
mSensor.registerListener(this, sSensor,SensorManager.SENSOR_DELAY_NORMAL);
// sSensor = mSensor.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
// mSensor.registerListener(this, sSensor,SensorManager.SENSOR_DELAY_NORMAL);
sSensor = mSensor.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
mSensor.registerListener(this, sSensor,SensorManager.SENSOR_DELAY_NORMAL);
}
return super.onStartCommand(intent, flags, startId);
}
#Override
#Override
public void onSensorChanged(SensorEvent event) {
Log.i(EXTRA_MESSAGE, "Sensor data arrived");
if(isConnected )
{
String toSend = Integer.toString(event.sensor.getType())+ ":" + Long.toString(event.timestamp)+ ":";
for(float f : event.values){
toSend = toSend + Float.toString(f)+":";
}
//
connected.write(toSend.getBytes());
}
}
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device) {
// Use a temporary object that is later assigned to mmSocket,
// because mmSocket is final
BluetoothSocket tmp = null;
mmDevice = device;
// Get a BluetoothSocket to connect with the given BluetoothDevice
try {
// MY_UUID is the app's UUID string, also used by the server code
tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
Log.i(EXTRA_MESSAGE,"connectThread started successfully");
} catch (IOException e) { }
mmSocket = tmp;
}
public void run() {
// Cancel discovery because it will slow down the connection
try {
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
mmSocket.connect();
Log.i(EXTRA_MESSAGE,"connectThread connect successfully");
} catch (IOException connectException) {
// Unable to connect; close the socket and get out
Log.i(EXTRA_MESSAGE,"connectThread connect exception");
try {
mmSocket.close();
} catch (IOException closeException) { }
}
// Do work to manage the connection (in a separate thread)
mHandler.obtainMessage(SUCCESS_CONNECT, mmSocket).sendToTarget();
}
/** Will cancel an in-progress connection, and close the socket */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public boolean shouldContinue = true;
int nBytes =0;
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the input and output streams, using temp objects because
// member streams are final
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
Log.i(EXTRA_MESSAGE,"connectedThread sockets");
} catch (IOException e) { }
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer; // buffer store for the stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while(shouldContinue) {
try {
// Read from the InputStream
buffer = new byte[1024];
bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI activity
Log.e(EXTRA_MESSAGE, " We read");
mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
break;
}
}
}
/* Call this from the main activity to send data to the remote device */
public void write(byte[] bytes) {
try {
Log.i(EXTRA_MESSAGE,"Service->Server");
mmOutStream.write(bytes);
nBytes += bytes.length;
Log.i(EXTRA_MESSAGE,"ok" + String.valueOf(nBytes ));
} catch (IOException e) {
Log.i(EXTRA_MESSAGE,"exception");
}
}
/* Call this from the main activity to shutdown the connection */
public void cancel() {
try {
shouldContinue = false;
mmSocket.close();
} catch (IOException e) { }
}
}
Also my c# thread is as follows
public void ServerConnectThread()
{
serverStarted = true;
int counter = 0;
updateUI("Server started, waiting for clients");
BluetoothListener blueListener = new BluetoothListener(mUUID);
blueListener.Start();
BluetoothClient conn = blueListener.AcceptBluetoothClient();
updateUI("Client has connected");
Stream mStream = conn.GetStream();
while (true)
{
try
{
//handle server connection
byte[] received = new byte[1024];
mStream.Read(received, 0, received.Length);
counter += Encoding.ASCII.GetString(received).Length;
String[] fields = Encoding.ASCII.GetString(received).Split(':');
double[] data = new double[3];
for (int i = 2; i < 5; i++) data[i-2] = double.Parse(fields[i]);
//mSource.notifyObserver(Int16.Parse(fields[0]), data);
updateUI(counter.ToString() + " "+ fields[2]+ ":" + fields[3] + ":" + fields[4]);
byte[] sent = Encoding.ASCII.GetBytes("Hello World");
mStream.Write(sent, 0, sent.Length);
}
catch (IOException exception)`enter code here`
{
updateUI("Client has disconnected!!!!");
}
}
}
One final thing is I've found thousands of 561K android program which sounded a little interesting.
Ok I found my own problem. Basically I m sending a reply from my client when I got the sensor data and It is not handled by android app.
I have a small C# application that communicate with a server and get some data via API request, using POST method. It is an Apache server by the way.
My problem is that my C# app sends a tons of requests continuously, and the server creates a tons of log files.
I use a BackgroundWorker and I want to pause it for a few seconds, but Thread.Sleep(5000) doesn't working.
This app is running in the system tray it doesn't have a GUI, just get some content, and print them out.
Code:
private void _bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
JSONParser parser = new JSONParser(_config.Prop.server + "content/api.php", "print", "getAll");
try
{
while (!_bgWorker.CancellationPending)
{
try
{
JSONPrintNeeds needs = parser.DownloadAll();
List<JSONPrintNeed> temp = new List<JSONPrintNeed>();
foreach (JSONPrintNeed need in needs.data)
{
temp.Add(need);
}
foreach (JSONPrintNeed need in temp)
{
Printer printer = new Printer(need.megrendeles);
printer.PrintController = new StandardPrintController();
List<String> installed = new List<String>();
for (int i = 0; i < PrinterSettings.InstalledPrinters.Count; i++)
{
installed.Add(PrinterSettings.InstalledPrinters[i]);
}
if (installed.Contains(need.nyomtato))
{
printer.PrinterSettings.PrinterName = need.nyomtato;
}
int format = int.Parse(need.format);
switch (format)
{
case 0:
default: // txt
printer.Print();
break;
case 1: // html
SetDefaultPrinter(need.nyomtato);
browser.DocumentText = need.megrendeles;
browser.Print();
break;
}
JSONResult result = parser.DeleteOne(int.Parse(need.ny_id));
}
parser.DeleteAll();
Thread.Sleep(5000);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
you can use EventWaitHandle for sync threads.
EventWaitHandle flag = new EventWaitHandle(false, EventResetMode.AutoReset);
if (stop)
{
flag.WaitOne(5000);
}
This is one of my first issues. Whenever I exit out the program, tcpClient.Connect() takes forever to close. I've tried a ton of things, and none of them seem to work.
Take a look at the CreateConnection() thread, if the client isn't connected yet... and I close the program, it takes forever to close. If it IS connected, it closes immediately. I know this can be done with some kind of timeout trick, but i've tried a few and none of them worked.
Please provide a code example if you can.
Also, is there any good tutorial out there for C# on reading/writing the actual bytes with a buffer instead of this version that just does masterServer.writeLine() and masterServer.readline() or are they both just as efficient?
If you see anything else to help me improve this... by all means, go ahead. I'm trying to teach myself how to do this and I have no help, so don't let me go on doing something wrong if you see it!!! Thanks guys!
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;
namespace RemoteClient
{
public partial class Form1 : Form
{
private int MyPort = 56789;
private IPAddress myIp = IPAddress.Parse("210.232.115.79");
private IPAddress serverIp = IPAddress.Parse("72.216.18.77"); // Master Server's IP Address
public static TcpClient masterServer = new TcpClient();
private StreamWriter responseWriter;
private StreamReader commandReader;
private Thread connectionThread;
private Thread commandsThread;
private bool RequestExitConnectionThread { get; set; }
private delegate void AddMessageDelegate(string message, int category);
private delegate void ConnectedDelegate();
private bool isConnected { get; set; }
public Form1()
{
InitializeComponent();
isConnected = false;
}
private void LogMessage(string message, int category)
{
if (category == 1)
{
ListViewItem item = new ListViewItem(message);
item.BackColor = Color.LightGreen;
item.UseItemStyleForSubItems = true;
Log.Items.Add(item).SubItems.Add(DateTime.Now.ToString());
}
if (category == 2)
{
ListViewItem item = new ListViewItem(message);
item.BackColor = Color.Orange;
item.UseItemStyleForSubItems = true;
Log.Items.Add(item).SubItems.Add(DateTime.Now.ToString());
}
if (category == 3)
{
ListViewItem item = new ListViewItem(message);
item.BackColor = Color.Yellow;
item.UseItemStyleForSubItems = true;
Log.Items.Add(item).SubItems.Add(DateTime.Now.ToString());
}
if (category == 0)
{
Log.Items.Add(message).SubItems.Add(DateTime.Now.ToString());
}
}
private void Connected()
{
LogMessage("Found and Accepted Master Server's connection. Waiting for reply...",1);
Status.Text = "Connected!";
Status.ForeColor = Color.Green;
commandsThread = new Thread(new ThreadStart(RecieveCommands));
sendClientInfo();
}
private void exitButton_Click(object sender, EventArgs e)
{
Disconnect();
exitButton.Enabled = false;
exitButton.Text = "Closing...";
if (connectionThread != null)
{
while (connectionThread.IsAlive)
{
Application.DoEvents();
}
}
this.Close();
}
private void Form1_Load(object sender, EventArgs e)
{
Connect();
}
private void Disconnect()
{
RequestExitConnectionThread = true;
if (masterServer != null)
masterServer.Close();
if (connectionThread != null)
connectionThread.Abort();
LogMessage("Closing Client. Please wait while Program threads end.", 2);
}
private void Disconnected()
{
Status.Text = "Disconnected";
Status.ForeColor = Color.Red;
Connect();
}
private void Connect()
{
LogMessage("Attempting to connect to Master Server...", 1);
connectionThread = new Thread(new ThreadStart(CreateConnection));
connectionThread.Start();
}
private void CreateConnection()
{
int i = 1;
bool success = false;
while (!success)
{
try
{
using (masterServer = new TcpClient())
{
IAsyncResult result = masterServer.BeginConnect(serverIp, MyPort, null, null);
success = result.AsyncWaitHandle.WaitOne(1000, false);
}
if (success)
{
BeginInvoke(new ConnectedDelegate(this.Connected), new object[] {});
break;
}
else
{
Thread.Sleep(2000);
BeginInvoke(new AddMessageDelegate(LogMessage), new object[] { "Connection Retry # " + i.ToString() + ". Master Server hasn't been started yet.", 3 });
}
}
catch
{
MessageBox.Show("Error!");
}
i++;
}
}
private void RecieveCommands()
{
MessageBox.Show("Hello!");
commandReader = new StreamReader(masterServer.GetStream());
string CommandResponse = commandReader.ReadLine();
string Command = null;
if (CommandResponse != null)
MessageBox.Show("Recieved Command that was NOT null!");
if (CommandResponse != null)
{
MessageBox.Show("Recieved null response!");
BeginInvoke(new AddMessageDelegate(LogMessage), new object[] { "Disconnected From Master Server. Reason: Recieved Null response.", 1 });
Disconnected();
}
else if (CommandResponse.StartsWith("0"))
{
MessageBox.Show("Recieved 0 as a response!");
Command = CommandResponse.Substring(2).Trim();
isConnected = false;
BeginInvoke(new AddMessageDelegate(LogMessage), new object[] { "Disconnected From Master Server. Reason: " + Command, 1 });
}
else if (CommandResponse.StartsWith("1"))
{
MessageBox.Show("Recieved 1 as a response!");
isConnected = true;
BeginInvoke(new AddMessageDelegate(LogMessage), new object[] { "Connected to Master Server Successfully.", 1 });
}
}
//************************** RESPONSE'S BELOW HERE ************************* \\
private void sendClientInfo()
{
responseWriter = new StreamWriter(masterServer.GetStream());
responseWriter.WriteLine(myIp.ToString());
responseWriter.Flush();
}
}
}
Sorry, after testing it: NO, it does not use an async waithandle, it blocks the process :(
I prefer this solution, which also blocks the process but only by the period you specify, in this case 5 seconds:
using (TcpClient tcp = new TcpClient())
{
IAsyncResult ar = tcp.BeginConnect("127.0.0.1", 80, null, null);
System.Threading.WaitHandle wh = ar.AsyncWaitHandle;
try
{
if (!ar.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(5), false))
{
tcp.Close();
throw new TimeoutException();
}
tcp.EndConnect(ar);
}
finally
{
wh.Close();
}
}
From: http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/2281199d-cd28-4b5c-95dc-5a888a6da30d
The following example uses both async connection and async timeout control:
var tcp = new TcpClient();
var ar = tcp.BeginConnect(Ip, Port, null, null);
Task.Factory.StartNew(() =>
{
var wh = ar.AsyncWaitHandle;
try
{
if (!ar.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(5), false))
{
// The logic to control when the connection timed out
tcp.Close();
throw new TimeoutException();
}
else
{
// The logic to control when the connection succeed.
tcp.EndConnect(ar);
}
}
finally
{
wh.Close();
}
});
connect with timeout of 2000 ms:
AutoResetEvent connectDone = new AutoResetEvent( false );
TcpClient client = new TcpClient();
client.BeginConnect(
"127.0.0.1", 80,
new AsyncCallback(
delegate( IAsyncResult ar ) {
client.EndConnect( ar );
connectDone.Set();
}
), client
);
if( !connectDone.WaitOne( 2000 ) ) {
Console.WriteLine( "network connection failed!" );
Environment.Exit( 0 );
}
Stream stream = client.GetStream();
Adding a check within your connection process to cancel it if the program is exiting should help.
Try adding this in CreateConnection() inside your while(!success) loop but before your try block:
if(RequestExitConnectionThread)
{
break;
}
Here's an example of an asynchronous BeginConnect() call:
myTcpClient.BeginConnect("localhost", 80, OnConnect, null);
OnConnect function:
public static void OnConnect(IAsyncResult ar)
{
// do your work
}