我在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();
}
}
}
你的问题是,只有当workerCompleted
完成时才会调用backgroundWorker
方法。因为你的TCPServer
方法有一个永远不会发生的无限循环。
你可以使用你的ReportProgress
的backgroundWorker
功能。但我认为根据每秒200-300次更新标签并不是一个好主意。
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,但它不应该运行无休止的任务。