c# - 为什么我不能递归调用 Worker_DoWork 函数?
问题描述
我在 c# 中有一个使用 Sytem.Net.Sockets 的 tcp 服务器和客户端。我的工人功能如下
private void Worker_DoWork(object sender, DoWorkEventArgs e)
{
byte[] buffer = new byte[1];
socket.Receive(buffer);
chatTextBox.Text = buffer[0].ToString();
}
我在创建服务器后调用它,一旦它收到来自客户端的消息,它就会将其写入屏幕并停止。我的问题是我希望它最后再次调用自己,以便等待另一条消息显示。如果我只是添加 worker.RunWorkerAsync(); 在底部它不起作用,但是如果我只是从另一个按钮调用它,它会起作用并接收和写入消息。
解决方案
BackgroundWorker “包裹”在一个线程周围,并帮助您完成所有工作。这是一种非常过时的多任务处理方法,你不应该再在生产代码中使用它。然而,它也是我所知道的多任务处理的最佳“训练轮”。
你的基本方法是有缺陷的。BGW 不允许这样做实际上只是在帮助您学习需要学习的东西。代码中的错误列表:
- 您正在 DoWork 中直接访问 GUI 元素。不要那样做。只在 ReportProgress 和 RunWorker 完成事件中编写 UI。这是一个通用的多线程规则,这得益于 BGW 的设计。
- 您正在尝试在线程完成之前重新启动线程。如果您想重新启动它, RunWorkerCompleted 将是正确的地方
- 然而,更明智的做法是让 BackgroundWorker 的核心成为一个半无限循环。一直运行到取消的东西。通常通过报告分发信息不是一个好主意,但在这种情况下,这是我最好的主意。
我能给你的唯一另一件事是我的旧 BGW 示例代码:
#region Primenumbers
private void btnPrimStart_Click(object sender, EventArgs e)
{
if (!bgwPrim.IsBusy)
{
//Prepare ProgressBar and Textbox
int temp = (int)nudPrim.Value;
pgbPrim.Maximum = temp;
tbPrim.Text = "";
//Start processing
bgwPrim.RunWorkerAsync(temp);
}
}
private void btnPrimCancel_Click(object sender, EventArgs e)
{
if (bgwPrim.IsBusy)
{
bgwPrim.CancelAsync();
}
}
private void bgwPrim_DoWork(object sender, DoWorkEventArgs e)
{
int highestToCheck = (int)e.Argument;
//Get a reference to the BackgroundWorker running this code
//for Progress Updates and Cancelation checking
BackgroundWorker thisWorker = (BackgroundWorker)sender;
//Create the list that stores the results and is returned by DoWork
List<int> Primes = new List<int>();
//Check all uneven numbers between 1 and whatever the user choose as upper limit
for(int PrimeCandidate=1; PrimeCandidate < highestToCheck; PrimeCandidate+=2)
{
//Report progress
thisWorker.ReportProgress(PrimeCandidate);
bool isNoPrime = false;
//Check if the Cancelation was requested during the last loop
if (thisWorker.CancellationPending)
{
//Tell the Backgroundworker you are canceling and exit the for-loop
e.Cancel = true;
break;
}
//Determin if this is a Prime Number
for (int j = 3; j < PrimeCandidate && !isNoPrime; j += 2)
{
if (PrimeCandidate % j == 0)
isNoPrime = true;
}
if (!isNoPrime)
Primes.Add(PrimeCandidate);
}
//Tell the progress bar you are finished
thisWorker.ReportProgress(highestToCheck);
//Save Return Value
e.Result = Primes.ToArray();
}
private void bgwPrim_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
pgbPrim.Value = e.ProgressPercentage;
}
private void bgwPrim_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
pgbPrim.Value = pgbPrim.Maximum;
this.Refresh();
if (!e.Cancelled && e.Error == null)
{
//Show the Result
int[] Primes = (int[])e.Result;
StringBuilder sbOutput = new StringBuilder();
foreach (int Prim in Primes)
{
sbOutput.Append(Prim.ToString() + Environment.NewLine);
}
tbPrim.Text = sbOutput.ToString();
}
else
{
tbPrim.Text = "Operation canceled by user or Exception";
}
}
#endregion
推荐阅读
- javascript - keystone.js 中的链式关系
- javascript - 字段验证器错误 Jquery
- xpath - XPATH - 在命名元素之后抓取 div 的内容
- html - 可以显示网页cookies的HTML按钮
- c# - 复合键、EF6 和插入顺序
- sql-server - 如何检查嵌套存储过程是否在 tsqlt 中执行
- reactjs - Keycloak json 配置文件,React 和 Router 4
- node.js - 环回验证在更新查询中不起作用?
- javascript - CORS - 对预检请求的响应未通过访问控制检查
- java - HttpClient - 使用 Tomcat Webdav 上传 JAR 文件会导致“jarfile 无效或损坏”