我正在通过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();
}
}
}
答案 0 :(得分:0)
您的问题是,workerCompleted
方法只会在backgroundWorker
完成时被调用。由于您的TCPServer
方法具有无限循环,因此永远不会发生。
您可以使用ReportProgress
的{{1}}功能。但是我认为根本不每秒200-300次更新标签是个好主意。
答案 1 :(得分:0)
BackgroundWorker只会在需要定期引发事件以更新ui的另一个线程上运行任务
您的workerCompleted
方法用于更新label1.Text,但该方法仅在辅助工作完成且看起来无意完成时才被调用。
您可以做几件事:
您可以向工作程序注册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进入另一个线程的任务,但不应运行无尽的任务。