I'm having this issue. I need to be able to append the incoming messages to txtConsole from within OnMessage, but I'm getting an Illegal Cross Thread error. How do I get around this? I'm pretty basic when it comes to C# so some code (no psuedocode) with explanations would be helpful please.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Apache.NMS;
using Apache.NMS.Util;
namespace WindowsFormsApplication1
{
public partial class frmConsole : Form
{
public frmConsole()
{
InitializeComponent();
}
private void Form1_Load(object sender, System.EventArgs e)
{ }
public void cmdConnect_Click(object sender, EventArgs e)
{
// Output to the user that the connection is being set up
txtConsole.AppendText(Environment.NewLine + "Setting up connection...");
// Define the feed URL
IConnectionFactory factory = new NMSConnectionFactory(new Uri("stomp:tcp://datafeeds.networkrail.co.uk:61618"));
// Define the credentials
IConnection connection = factory.CreateConnection("REDACTED", "REDACTED");
// Create the session
ISession session = connection.CreateSession();
// Specify which feed - we want TRAIN_MVT_ALL_TOC to listen for all train movements
IDestination destination = session.GetDestination("topic://" + "TRAIN_MVT_ALL_TOC");
// Let the end user know where we will be subscribing to
txtConsole.AppendText(Environment.NewLine + "Will attempt subscription to " + destination);
// Create a consumer for the feed
IMessageConsumer consumer = session.CreateConsumer(destination);
// Let the end user know we are about to connect...
txtConsole.AppendText(Environment.NewLine + "Connecting...");
// Connection details are now all set up. Start the connection...
connection.Start();
// Check we are connected
if (connection.IsStarted == false)
{
txtConsole.AppendText(Environment.NewLine + "Connection closed.");
connection.Close();
}
// Now we need to handle messages using a MessageListener where we pass it to the OnMessage void.
consumer.Listener += new MessageListener(OnMessage);
txtConsole.AppendText(Environment.NewLine + "Connection established. Waiting for messages...");
// End of void
}
public void OnMessage(IMessage message)
{
ITextMessage msg = (ITextMessage)message;
message.Acknowledge();
txtConsole.AppendText(Environment.NewLine + msg.Text);
}
}
}
The reason you're getting that error is because you're trying to update a UI element from a non-UI thread. You can call the control's Invoke method to force it to run on the UI thread.
public void OnMessage(IMessage message)
{
ITextMessage msg = (ITextMessage)message;
message.Acknowledge();
if (txtConsole.InvokeRequired)
{
txtConsole.Invoke(new Action(() =>
{
txtConsole.AppendText(Environment.NewLine + msg.Text);
}));
}
else
{
txtConsole.AppendText(Environment.NewLine + msg.Text);
}
}
That exception appears when you try to access other thread (for example, UI Thread), from another different thread.
You can solve that calling
Dispatcher.BeginInvoke(() => delegate{// Here the code});
from any thread you want
How to Properly Handle Cross-thread Events and Update a Label with BeginInvoke and BackgroundWorker
Cross Thread UI control access
Just replace txtConsole.AppendText in method OnMessage with
txtConsole.Invoke((Action)(() => txtConsole.AppendText(Environment.NewLine + msg.Text)));
Related
I am connecting to Apache Active MQ which is hosted on AWS to integrate my app to a custom service. I need to keep this running always, not one time like it's right now. The code below works, but only for one message, I need to maintain the connection active all the time listening in order to receive all the messages.
Here is the code.
using Apache.NMS;
using Apache.NMS.Util;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ApacheMQAsync
{
class Program
{
protected static ITextMessage message = null;
public static void Main(string[] args)
{
Uri connecturi = new Uri("URL:61617");
Console.WriteLine("About to connect to " + connecturi);
// NOTE: ensure the nmsprovider-activemq.config file exists in the executable folder.
IConnectionFactory factory = new Apache.NMS.ActiveMQ.ConnectionFactory(connecturi);
IConnection connection = factory.CreateConnection("username", "password");
ISession session = connection.CreateSession();
IDestination destination = SessionUtil.GetDestination(session, "queue://FOO.BAR");
Console.WriteLine("Using destination: " + destination);
// Create a consumer and producer
IMessageConsumer consumer = session.CreateConsumer(destination);
consumer.Listener += new MessageListener(OnMessage);
connection.Start();
// Wait for the message
if (message == null)
{
Console.WriteLine("No message received!");
}
else
{
Console.WriteLine("Received message with ID: " + message.NMSMessageId);
Console.WriteLine("Received message with text: " + message.Text);
}
}
protected static void OnMessage(IMessage receivedMsg)
{
message = receivedMsg as ITextMessage;
message.Acknowledge();
}
}
}
On the console it displays following
No message received!
and after few seconds the console exist?
There's no real magic there, you need to do something to keep your application running such as pausing on console input or looping on a sleep or other wait type call and then checking something to see if your application should continue. The JMS client isn't guaranteed to keep your application open and running and you should never rely on it to.
I'm porting initialization code for a Myo armband to a WPF application, that uses a C# wrapper, http://goo.gl/HfwqQe to interact with the device.
But when I add the initialization code under the InitializeComponent(); in the code behind of my user control, the line to update a textbox with connection status is never triggered, this.Dispatcher.Invoke((Action)(() =>
I debugged this by setting a breakpoint on the line just before the dispatcher code and this is being called hub.MyoConnected += (sender, e) => meaning that the Myo has connected, but the following dispatcher line after that updates the statusTbxis never called and skipped over.
Anyone have any idea here what could be causing this?
I'm not sure why it won't output the connection status to the textbox. The same code worked before but this is a new version of the C# wrapper I'm using.
The console samples work fine, http://goo.gl/RFHLym and output connection to console, but I can't get it to output the connection to textbox instead.
This is the complete code for getting the Myo arm band's connection status :
using MyoSharp.Communication;
using MyoSharp.Device;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace MyoTestv4
{
/// <summary>
/// Interaction logic for ProductsView.xaml
/// </summary>
public partial class AdductionAbductionFlexionView : UserControl
{
public AdductionAbductionFlexionView()
{
InitializeComponent();
// create a hub that will manage Myo devices for us
using (var channel = Channel.Create(ChannelDriver.Create(ChannelBridge.Create())))
using (var hub = Hub.Create(channel))
{
//set a bpoint here, gets triggered
// listen for when the Myo connects
hub.MyoConnected += (sender, e) =>
{
//set a bpoint here, doesn't get triggered
this.Dispatcher.Invoke((Action)(() =>
{
statusTbx.Text = "Myo has connected! " + e.Myo.Handle;
//Console.WriteLine("Myo {0} has connected!", e.Myo.Handle);
e.Myo.Vibrate(VibrationType.Short);
}));
};
// listen for when the Myo disconnects
hub.MyoDisconnected += (sender, e) =>
{
this.Dispatcher.Invoke((Action)(() =>
{
statusTbx.Text = "Myo has disconnected!";
//Console.WriteLine("Oh no! It looks like {0} arm Myo has disconnected!", e.Myo.Arm);
e.Myo.Vibrate(VibrationType.Medium);
}));
};
// start listening for Myo data
channel.StartListening();
}
}
}
}
You get this error because channel and hub are disposed immediately after calling
channel.StartListening();
using is a convenient way to dispose object for you, in this case, this is not desired. Please refer to using Statement (C# Reference) for more info.
Try these steps to fix the problem. 1. Declare channel and hub as private field of the class. 2. Do not use using keyword. 3. Remember to dispose hub and channel when AdductionAbductionFlexionView is disposed of.
public partial class AdductionAbductionFlexionView : UserControl
{
IChannel channel;
IHub hub;
public AdductionAbductionFlexionView()
{
InitializeComponent();
// create a hub that will manage Myo devices for us
channel = Channel.Create(ChannelDriver.Create(ChannelBridge.Create()));
hub = Hub.Create(channel);
//set a bpoint here, gets triggered
// listen for when the Myo connects
hub.MyoConnected += (sender, e) =>
{
//set a bpoint here, doesn't get triggered
this.Dispatcher.Invoke((Action)(() =>
{
statusTbx.Text = "Myo has connected! " + e.Myo.Handle;
//Console.WriteLine("Myo {0} has connected!", e.Myo.Handle);
e.Myo.Vibrate(VibrationType.Short);
}));
};
// listen for when the Myo disconnects
hub.MyoDisconnected += (sender, e) =>
{
this.Dispatcher.Invoke((Action)(() =>
{
statusTbx.Text = "Myo has disconnected!";
//Console.WriteLine("Oh no! It looks like {0} arm Myo has disconnected!", e.Myo.Arm);
e.Myo.Vibrate(VibrationType.Medium);
}));
};
// start listening for Myo data
channel.StartListening();
}
}
I have the following code in a WPF application that shows a splash screen while a long running process happens. On all of our developer machines and testing machines this works perfectly. However on some customer machines this code is leaving the main process running.
I've tried various methods of calling a shutdown including Environment.Exit(0); and we are still seeing this process left running after it has completed.
Is there something that I have missed about how my task and the application are interacting?
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.IO.Pipes;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace GKUpdate
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
MainWindow oWindow;
string sPipeName;
string sGKPath;
//Call base startup
base.OnStartup(e);
//Find the GK path
sPipeName = FindArgument(e.Args, "n");
sGKPath = FindArgument(e.Args, "p");
//Check if we have a path
if (!string.IsNullOrEmpty(sGKPath))
{
//Start listening
Task.Factory.StartNew(() => ListenForSuccess(sPipeName, sGKPath));
//Show the splash window
oWindow = new MainWindow();
oWindow.Show();
}
else
{
//Exit
this.Shutdown();
}
}
private string FindArgument(string[] oArgs, string sArgumentName)
{
string sFilter;
string sArgument;
//Get the argument
sFilter = string.Format("/{0}=", sArgumentName).ToLower();
sArgument = oArgs.FirstOrDefault(x => x.ToLower().StartsWith(sFilter));
//Check if we found the argument
if (!string.IsNullOrEmpty(sArgument) && sArgument.Length > sFilter.Length)
{
//Set the argument
sArgument = sArgument.Substring(sFilter.Length).Trim('"');
}
else
{
//Set null
sArgument = null;
}
//Return the argument
return sArgument;
}
private void ListenForSuccess(string sPipeName, string sGKPath)
{
int iStatus;
try
{
//Set default status
iStatus = -1;
//Loop until the service is online
do
{
//Create the named pipe
using (NamedPipeClientStream oNamedPipe = new NamedPipeClientStream(".", sPipeName, PipeDirection.InOut))
{
//Connect the pipe allowing 5 mins
oNamedPipe.Connect(300000);
//Send the byte asking for a status report
oNamedPipe.WriteByte(0);
oNamedPipe.WaitForPipeDrain();
//Read the return
iStatus = oNamedPipe.ReadByte();
//Disconnect
oNamedPipe.Close();
}
} while (iStatus != 1);
//Check if we can do the success actions
if (iStatus == 1)
{
//Start GateKeeper using the remaining command arguments
Process.Start(sGKPath, string.Join(" ", Environment.GetCommandLineArgs().Skip(3)));
}
}
catch (Exception)
{
//Do nothing
}
finally
{
//Exit the application
Application.Current.Dispatcher.InvokeShutdown();
}
}
}
}
Check the Threads window is visual studio. One of your non-background threads is not running to completion when your application closes. I expect that you are still 'listening' at this point.
How you handle this is up to you but i recommend implementing task cancellation.
There can be multiple reason. first you have to check window Event Viewer, you will able to find actual reason.
also you should handle DispatcherUnhandledException="Application_DispatcherUnhandledException". this will show actual error.
in App.XAML :
DispatcherUnhandledException="Application_DispatcherUnhandledException"
and in App.cs:
private void Application_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
e.Handled = true;
}
Your background thread is blocked waiting for the pipe to connect. You need to close the pipe from the foreground thread with an oNamedPipe.Close(). As Erno de Weerd says, you also need to make sure you can exit your do/while loop once the pipe aborts.
A nicer way would be to pass in a CancellationToken to the task, and use that to close the pipe when the foreground thread requests cancellation. You can then also check the cancellation state in your loop.
See How to force Task.Factory.StartNew to a background thread? to mark a Task.Factory.StartNew as a background thread so the thread is stopped as soon as all 'foreground' threads have stopped execution:
Task.Factory.StartNew(action,
CancellationToken.None,
TaskCreationOptions.None,
TaskScheduler.Default).ContinueWith(completeAction);
I put a lot of information in this issue because I have no idea what will be relavent
Issue:
I am having an issue with a program I am working on where when running it, it will freeze my whole computer and return no error (I am completely incapable of doing anything CTRL+ALT+DEL doesn't even work). This program accepts a connection from a android client and atm the android client is not configured correctly so the connection is being rejected.
Question:
How can I stop my program from freezing my entire machine?
Conjecture:
I have a few theories as to what is going on but no idea how to fix them. I have read that this may have something to do with me running a single threaded process inside my async worker but I am not sure that the socket is a single threaded process. Also I am not entirely sure how I am supposed to deal with exceptions in a backgroundworker so I just let it fall back to the RunWorkerCompletedEventArgs then retrieve the error message from there.
What I have tried:
- I tried putting try catches every where then removing try catches nothing seems to be able to capture this error
- I checked my systems event log and nothing is showing up except my restarts after my computer freezes
- I have attempted to isolate the issue but it can literally happen at any point from the program starting till when I attempt to connect
Setup:
I am running the program out of visual studio 2012 professional on a windows 8 pro machine. The computer I am on has a i7-3770K 3.50GHz and 32GB of ram. The application that is attempting to make a connection to mine is a Android application and the credentials are incorrect when it is attempting to connect. Visual Studio is running off my main hard drive and building the project on another drive.
Closing:
With all that said would some one please be willing to help me? If you need any more information I will be happy to provide it, please ask.
Main Method:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
namespace Server
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class SourceServer : Window
{
private BackgroundWorker worker = new BackgroundWorker();
public SourceServer()
{
InitializeComponent();
StartListeningForConnections();
}
private void StartListeningForConnections()
{
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
worker.WorkerReportsProgress = true;
if (worker.IsBusy != true)
{
worker.RunWorkerAsync();
}
}
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
worker.ReportProgress(0, "Source server version 0.0.0.1ib started");
LoginServer oLoginServer = new LoginServer();
oLoginServer.StartListening(worker);
}
private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
try
{
lvOutput.Items.Add(e.UserState.ToString());
}
catch (Exception exception)
{
lvOutput.Items.Add(exception.StackTrace);
}
}
private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
System.IO.File.WriteAllText(Environment.CurrentDirectory + #"\log.txt", e.Error.StackTrace + " /n " + e.Error.Message);
}
else
{
MessageBox.Show("Error was null");
}
worker.Dispose();
}
}
}
SSL Socket Connection:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Windows;
using System.Windows.Controls;
using System.ComponentModel;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using MySql.Data.MySqlClient;
using System.IO;
namespace Server
{
public class LoginServer
{
// Incoming data from the client.
public static string data = null;
public static X509Certificate serverCertificate = null;
public delegate void UpdateListView(ListView oOutput);
public void StartListening(BackgroundWorker worker)
{
// Data buffer for incoming data.
byte[] bytes = new Byte[1024];
// Establish the local endpoint for the socket.
IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[1];
serverCertificate = X509Certificate.CreateFromCertFile(#"server.crt");
TcpListener oServer = new TcpListener(ipAddress, 12345);
// Bind the socket to the local endpoint and
// listen for incoming connections.
// Start listening for connections.
while (true)
{
Thread.Sleep(100);
worker.ReportProgress(0, "Waiting for connection....");
// Program is suspended while waiting for an incoming connection.
//Socket handler = listener.Accept();
oServer.Start();
TcpClient oClient = oServer.AcceptTcpClient();
Stream oStream = oClient.GetStream();
SslStream oSSLStream = new SslStream(oStream);
data = null;
// An incoming connection needs to be processed.
string sUsername = "place holder";
string sPassword = "place holder";
while (true)
{
bytes = new byte[1024];
int bytesRec = oSSLStream.Read(bytes, 0, bytes.Length);
data += Encoding.ASCII.GetString(bytes, 0, bytesRec);
string[] sCredentials = data.Split("|".ToCharArray()[0]);
sUsername = sCredentials[0];
sPassword = sCredentials[1];
if (data.IndexOf("<EOF>") > -1)
{
break;
}
}
// Show the data on the console.
worker.ReportProgress(0, "Connection Recieved : ");
worker.ReportProgress(0, "Username: " + sUsername);
worker.ReportProgress(0, "Password: " + sPassword);
worker.ReportProgress(0, "");
// Echo the data back to the client.
byte[] msg;
if (sUsername.Equals("test") && sPassword.Equals("test"))
{
msg = Encoding.ASCII.GetBytes("approved<EOF>\n");
worker.ReportProgress(0, "approved");
oSSLStream.Write(msg, 0, msg.Length);
}
else
{
msg = Encoding.ASCII.GetBytes("rejected<EOF>\n");
worker.ReportProgress(0, "rejected");
oSSLStream.Write(msg, 0, msg.Length);
}
}
}
public void VerifyUser()
{
}
}
}
While I don't see any reason for this to lock up your entire computer, I do see a couple of reasons for the application to potentially hang...
Your while loop inside of your SSL server will never break unless your client writes '<EOF>' to the stream; which you would have to force it to do. I would likely do something similar to this:
while(( bytesRec = oSSLStream.Read(bytes,0,bytes.Length)) > 0 )
{
// Compare input & break
}
-- The while loop you have now ( without a thread sleep ) will consume all of your systems resources waiting for ... something that may never occur.
In a related issue - I note that your 'DoWork' method launches the listener - but does not start a new thread for this listener. This means that the listener is running inside of your interface thread - which will cause the interface ( and potentially more... ) to hang until the process is completed - which as stated, may never happen.
... Ahem... This last paragraph may be incorrect - you are running an async worker, so I may be incorrect in my second assessment.
Cheers, hope this is helpful.
I've had some hanging problems on Windows 8 that I never saw on Windows 7 (with VS2012). As you experienced it worked fine the first time but only locked up Visual Studio (and not my whole machine) and I had to force quit.
The Visual Studio 2012 Update 4 (which focuses on bug fixes and compatibility) seemed to fix it, although I didn't scientifically test this.
Note: As of 9/1/13 this is only the RC2 version so please check for newer versions, and edit this answer when RTM happens.
Ok, I studied a bit on asynchronous TCP network connection. I tried making one but failed. What I want to do is make sure the server or client is always ready to receive a chat and is able to send a chat any time. I do not want them to be on alternate mode.
e.g. Server Send while client waits to receive thus client can't send at that time.
I do not want that!
Did this on Windows Application. Once I connected, the system resource just shot to 100% =/
Server Code
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;
namespace AsyncServerChat
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private Socket g_server_conn;
private byte[] g_bmsg;
private bool check = false;
private void Form1_Load(object sender, EventArgs e)
{
IPEndPoint local_ep = new IPEndPoint(IPAddress.Any, 9050);
Socket winsock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
winsock.Bind(local_ep);
winsock.Listen(5);
winsock.BeginAccept(new AsyncCallback(Accept), winsock);
}
private void Accept(IAsyncResult iar)
{
Socket server_conn =(Socket) iar.AsyncState;
g_server_conn = server_conn.EndAccept(iar);
//label1.Text = "Connected. . .";
while (g_server_conn.Connected && check == false)
{
g_bmsg = new byte[1024];
check = true;
g_server_conn.BeginReceive(g_bmsg, 0, g_bmsg.Length, SocketFlags.None, new AsyncCallback(Recieve), g_server_conn);
}
}
private void Send(IAsyncResult iar)
{
Socket server_conn = (Socket)iar.AsyncState;
server_conn.EndSend(iar);
}
private void Recieve(IAsyncResult iar)
{
Socket server_conn =(Socket) iar.AsyncState;
server_conn.EndReceive(iar);
if (g_bmsg.Length != 0)
{
label1.Text = Encoding.ASCII.GetString(g_bmsg, 0, g_bmsg.Length);
check = false;
}
}
private void sendButton_Click(object sender, EventArgs e)
{
string strmsg = textBox1.Text;
byte[] bmsg= Encoding.ASCII.GetBytes(strmsg);
g_server_conn.BeginSend(bmsg, 0, bmsg.Length, SocketFlags.None, new AsyncCallback(Send), g_server_conn);
}
}
}
Client
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
namespace AsyncClientChat
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Socket g_client_conn;
byte[] g_bmsg;
private bool check = false;
private void Form1_Load(object sender, EventArgs e)
{
}
private void connectButton_Click(object sender, EventArgs e)
{
IPEndPoint remote_ep = new IPEndPoint(IPAddress.Parse(textBox1.Text), 9050);
g_client_conn = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
g_client_conn.BeginConnect(remote_ep, new AsyncCallback(Connect), g_client_conn);
}
private void Connect(IAsyncResult iar)
{
Socket client_conn =(Socket) iar.AsyncState;
client_conn.EndConnect(iar);
while (g_client_conn.Connected)
{
g_bmsg = new byte[1024];
check = true;
g_client_conn.BeginReceive(g_bmsg, 0, g_bmsg.Length, SocketFlags.None, new AsyncCallback(Recieve), g_client_conn);
}
}
private void Send(IAsyncResult iar)
{
Socket client_conn = (Socket)iar.AsyncState;
client_conn.EndSend(iar);
}
private void Recieve(IAsyncResult iar)
{
Socket client_conn = (Socket)iar.AsyncState;
client_conn.EndReceive(iar);
if (g_bmsg.Length != 0)
{
label1.Text = Encoding.ASCII.GetString(g_bmsg, 0, g_bmsg.Length);
check = false;
}
}
}
}
Well, the problem is the while loop in client method Connect.
Remove it because it loops infinitely raising CPU usage to 100% and it's useless.
BTW, you have another problems in your code:
CrossThread operation exception
For example in your Client.Recieve method you do:
label1.Text = Encoding.ASCII.GetString(g_bmsg, 0, g_bmsg.Length);
Actually, you're trying to set the label text from another thread (the one listening for received msgs) and this is not allowed;
Do something like this:
Create a Setter method for the label text:
private void SetLabelText(string txt)
{
if (label1.InvokeRequired)
label1.Invoke(new MethodInvoker(delegate { SetLabelText1(txt); }));
else
label1.Text = txt;
}
then use the setter instead of directly call label1.Text = ...:
SetLabelText(Encoding.ASCII.GetString(g_bmsg, 0, g_bmsg.Length));
EDIT to answer to OP comment:
For a good and extensive explanation of what is a thread, look at its wikipedia page.
Anyway, in simple words, a running process contains one or more threads and these are part of code that can be executed concurrently.
Starting from your TCP example, using Socket.Receive instead of Socket.BeginReceive you would have blocked the execution on Socket.Receive() call (I mean the lines of code after the one containing Receive method wouldn't be reached) until something is received.
This because Socket.Receive method runs on the same thread of the following code, and on each thread, the code is executed sequentially (i.e. line by line).
Conversely, using Socket.BeginReceive, behind the scene a new thread is created. This thread likely calls and stops on Socket.Receive method, and once received something it calls the method passed as parameter.
This makes Socket.BeginReceive asynchronous, while Socket.Receive is synchronous, and this is why I knew ther was another thread (when you hear asynchronous word, is extremely probable that you are dealing with multi-threading)
Thus, when you change label.Text you are actually setting it from another thread: the one created by Socket.BeginReceive.
I took a quick look at this code and I would start with the following suggestion.
Remove the looping from your Accept callback, just initiate the BeginReceive and let it be. Then in your Receive method, you can just initiate the next BeginReceive. This would apply for both the client and the server code, except of course for the client code you will remove the loop from your Connect callback method.
Then you should also watch out updating the UI controls from the callback methods, since the callback runs on the non-UI thread which can cause a host of problems. You should look at using Control.Invoke or Control.BeginInvoke to marshal a request back to the UI thread which can then update the controls.