I come from an embedded C background and I am working on my first C# application and I have hit a wall on this and my research is not panning out so I thought I would ask here.
Simple app, so far. I have a MainWindow that, among a bunch of other stuff, starts a TCPClient thread on a button click:
public partial class MainWindow : Window
{
....
TCPConnection myCon = new TCPConnection();
....
private void connectButton_Click(object sender, RoutedEventArgs e)
{
networkListBox.Items.Add("Connecting...");
myCon.Connect("localhost", updateNetworkListBox);
}
}
....
public void updateNetworkListBox(string message)
{
networkListBox.Items.Add(message);
}
And in TCPConnection.cs:
public class TCPConnection
{
....
public void Connect(string server, ReportDelegate reportDelegate)
{
this.server = server;
clientThread = new Thread(() => Client(this.server));
clientThread.Start();
reportDelegate("Started client thread...");
}
static void Client(string server)
{
try
{
Int32 port = 25565;
TcpClient client = new TcpClient(server, port);
Byte[] outgoingBytes = new Byte[1024];
string outgoingString = "Hello! I am " + Guid.NewGuid();
outgoingBytes = System.Text.Encoding.ASCII.GetBytes(outgoingString);
NetworkStream stream = client.GetStream();
stream.Write(outgoingBytes, 0, outgoingBytes.Length);
stream.Close();
client.Close();
}
The first thing I would like to do, now that TCP connection works is send a message back to the UI such as "Client thread connecting...", "Client thread connected..." and have it show up in the networkListbox.
Within the Connect() method, I was able to do this by using the delegate but this obviously will not work in the new thread since one is not able to directly access UI controls from another thread.
I have read loads of articles on this and I know that I probably want to use the Dispatcher to to do this. However, almost all of the examples I have seen have created a new thread within the current class and, for example, passed an anonymous method to Dispatcher.Invoke().
One exception to this discussion which advocated using an EventHandler and initializing it in the main window. That seems less than ideal but maybe I am wrong.
Further down, someone else advocated data sharing. Again, that seems less than ideal to me.
Other articles I have read appear to be out of date.
So, I welcome any explanations on how to go about this. It may be that I am just getting hung up syntactically but I suspect that, although I think I am mostly clear on delegates, lambdas, etc., I am probably hung up on what exactly needs to get done.
If you can show how it would be done in this specific example with some explanation, I would greatly appreciate it.
And maybe some specific questions on some points that are a little hazy for me:
1) Can my worker task access on it on its own or must it be provided with the UI's Dispatcher?
2) Should the UI provide a delegate that performs the dispatch or should the dispatch be coded in the worker task, referencing the UI Dispatcher?
Thanks very much.