如何处理BackgroundWorker中TCP客户端的连续接收?

问题描述 投票:0回答:2

我在TCP服务器/客户端连接的帮助下发送一个字符串值,其中包含我在C#应用程序中需要的一些数据。字符串值每秒更改200-300x。

现在,我现在想要做的是在标签中显示传入的字符串值。我已经阅读过关于在这种情况下使用BackgroundWorker类的内容,因为它会冻结UI。但不幸的是,它不起作用!我首先在一个简单的控制台应用程序中测试了连接,它完美地工作。你有没有看到我在这里做错了什么?

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();
        }

    }
}
c# tcp backgroundworker
2个回答
0
投票

你的问题是,只有当workerCompleted完成时才会调用backgroundWorker方法。因为你的TCPServer方法有一个永远不会发生的无限循环。

你可以使用你的ReportProgressbackgroundWorker功能。但我认为根据每秒200-300次更新标签并不是一个好主意。


0
投票

BackgroundWorker将在您需要定期引发事件以更新ui的另一个线程上运行您的任务

您的workerCompleted方法用于更新label1.Text,但该方法仅在工作程序完成时调用,并且看起来不打算完成。

所以你可以做几件事: 您可以向worker调用ProgressChanged事件处理程序,并在worker.ReportProgress(progress, data)处理程序中调用DoWork(您的TCPServer方法):

// 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();
}

或者你可以从work方法中删除while(true)循环并运行一次,然后在workerCompleted方法中再次启动worker:

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();
}

你也可以在这里寻找灵感How to update GUI with backgroundworker?

我有一种感觉,你需要将以下内容移动到工作线程:

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

这些看起来像将阻止ui线程的异步操作


我真的会穿什么鞋子:

因为您基本上需要一台服务器一直运行,并且您已经将它作为控制台应用程序运行。我会找到一种方法来运行应用程序并订阅其输出并在另一个ui应用程序中显示信息。

或者至少在单独的进程/线程中运行整个服务器部分并将更新发送到ui。

我认为BackgroundWorker的意图是运行一些任务,否则会阻止另一个线程中的UI,但它不应该运行无休止的任务。

© www.soinside.com 2019 - 2024. All rights reserved.