0

I am sending a string value containing some data I need in my C# application with help of a TCP Server/Client connection. The string value changes 200-300x per second.

Now, what I just want to do for now is to show the incoming strings values in a label. I've read about using a BackgroundWorker class for that case, since it would freeze the UI otherwise. But unfortunately, it doesn't work! I first tested the connection in a simple console application, there it worked perfectly. Do you may see what I'm doing wrong here?

namespace test
{
    public partial class Form1 : Form
    {

        BackgroundWorker worker;
        IPAddress ip;
        Socket s;
        TcpListener tcp;

        public Form1()
        {
            InitializeComponent();

            ip = IPAddress.Parse("1.2.3.4");
            tcp = new TcpListener(ip, 8001);

            worker = new BackgroundWorker();

            worker.DoWork += new DoWorkEventHandler(TCPServer);
            worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(workerCompleted);

        }

        string data = string.Empty;
        int k = 0;
        byte[] b = new byte[4096];
        private void TCPServer(object sender, DoWorkEventArgs e)
        {
             while (true)
            {
                k = s.Receive(b);
                data = Encoding.ASCII.GetString(b, 0, k);
                e.Result = data.ToString();
            }

        }

        private void workerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            label1.Text = e.Result.ToString();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            tcp.Start();
            s = tcp.AcceptSocket();
            worker.RunWorkerAsync();
        }

    }
}

2 Answers2

0

Your problem is, that the workerCompleted method will only be called when the backgroundWorker finished. Since your TCPServer Method has an infinite loop that will never happen.

You could use the ReportProgress functionality of your backgroundWorker. But I don't think it's a good idea to update your label 200-300 times per second at all.

RomCoo
  • 1,868
  • 2
  • 23
  • 36
0

The BackgroundWorker will just run your task on another thread you need to raise events periodically to update the ui

Your workerCompleted method is used to update label1.Text but that method will only be invoked when the worker job finished and it looks like it's not meant to finish.

So there are a couple of things you can do:
You can register a ProgressChanged event handler to the worker and call worker.ReportProgress(progress, data) in the DoWork handler (your TCPServer method):

// Add to init
worker.WorkerReportsProgress = true;
worker.ProgressChanged = new ProgressChangedEventHandler(WorkerProgressChanged);

private void TCPServer(object sender, DoWorkEventArgs e)
{
  while(true) 
  {
    k = s.Receive(b);
    data = Encoding.ASCII.GetString(b, 0, k);
    int progress = 0; // Or the actual progress if available 
    object param = data.ToString();
    worker.ReportProgress(progress, param);
  }
}

private void workerProgressChanged(object sender, ProgressChangedEventArgs e)
{
  label1.Text = e.Result.ToString();
}

Or you could remove the while(true) cycle from the work method and just run it once, then in the workerCompleted method start the worker again:

private void TCPServer(object sender, DoWorkEventArgs e)
{
  k = s.Receive(b);
  data = Encoding.ASCII.GetString(b, 0, k);
  e.Result = data.ToString();
}

private void workerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
  label1.Text = e.Result.ToString();
  worker.RunWorkerAsync();
}

You can also look for inspiration here How to update GUI with backgroundworker?

I have a feeling the you will need to move the following stuff to the worker thread:

TcpListener tcp.Start();
Socket s = tcp.AcceptSocket();

These look like an async actions that will block the ui thread


What I would actually do in your shoes:

Since you basically need a server running the whole time and you already have it working as a console application. I would find a way to run the application and subscribe to its output and display the info in another ui only application.

Or at least run the entire server part in a separate process/thread and send updates to the ui.

I think the intent of the BackgroundWorker is to run some tasks that would otherwise block the UI in another thread, but it's not supposed to run an endless task.

kidroca
  • 3,480
  • 2
  • 27
  • 44
  • 1
    Thank you a lot, removing the while(true)-loop and calling the RunWorkerAsync() method just again works perfectly! – Snowy White Apr 13 '19 at 13:26