C# 取消正在从网络流中连续读取的后台工作进程
我有一个TCP服务器在运行,它定期吐出2字节的消息 我正在尝试创建一个客户端表单,它连接到服务器并不断地从流中读取数据,直到我单击表单上的断开连接按钮 到目前为止,客户端工作正常,只是我无法断开连接。我将CancellationPending设置为true,但在dowork方法有机会设置e.Cancel之前,它似乎重置回false 我还确信,必须有一种更可接受的方式来持续读取流并写入表单——目前,我正在Worker Completed方法中调用RunWorkerAsync来实现循环C# 取消正在从网络流中连续读取的后台工作进程,c#,multithreading,tcp,backgroundworker,client-side,C#,Multithreading,Tcp,Backgroundworker,Client Side,我有一个TCP服务器在运行,它定期吐出2字节的消息 我正在尝试创建一个客户端表单,它连接到服务器并不断地从流中读取数据,直到我单击表单上的断开连接按钮 到目前为止,客户端工作正常,只是我无法断开连接。我将CancellationPending设置为true,但在dowork方法有机会设置e.Cancel之前,它似乎重置回false 我还确信,必须有一种更可接受的方式来持续读取流并写入表单——目前,我正在Worker Completed方法中调用RunWorkerAsync来实现循环 pr
private void Disconnect()
{
commsWorker1.CancelAsync();
}
private void ReadFromStream()
{
try
{
commsWorker1.RunWorkerAsync();
}
catch (Exception ex)
{
writeToBox("Error: " + ex.Message);
}
}
//background worker dowork method
private void BackGroundGetServerData(object sender, DoWorkEventArgs e)
{
if (true == commsWorker1.CancellationPending)
{
e.Cancel = true;
}
else
{
Byte[] dataArray = new Byte[2];
try
{
_DataStream.Read(dataArray, 0, 2);
String reply = System.Text.Encoding.ASCII.GetString(dataArray);
e.Result = reply;
}
catch (Exception ex)
{
}
}
}
//background worker workercompleted method
private void BackGroundDisplayMessages(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
//close connection here
}
else
{
writeToBox((String)e.Result);
commsWorker1.RunWorkerAsync();
}
}
}
}您不能在后台工作程序方法内部循环吗
private void BackGroundGetServerData(object sender, DoWorkEventArgs e)
{
while(true)
{
Byte[] dataArray = new Byte[2];
try
{
_DataStream.Read(dataArray, 0, 2);
String reply = System.Text.Encoding.ASCII.GetString(dataArray);
e.Result = reply;
}
catch (Exception ex)
{
return;
}
}
}
然后在断开连接后,只需关闭插座。这将导致异常
在while循环中抛出,您可以通过catch
块优雅地退出
编辑
:然后在读取每条消息后,您可以从循环中更新GUI。确保您正在更新的控件的句柄可用(假设它被称为框
):
在这种情况下,需要使用
BeginInvoke
,因为您试图从另一个线程更新GUI,这是不允许的。此方法将更新转发到GUI线程。似乎您正在worker complete方法中调用RunWorkerAsync(),并重置CancellationPending属性。我认为您可以通过在Disconnect()方法中添加一些disconnectFlag=true来解决这个问题;在WorkerComplete方法中,您应该添加:
if (e.Cancelled || disconnectFlag)
{
disconnectFlag = false;
//close connection here
} else ...
在这种情况下如何调用BackGroundDisplayMessages?如果我在DoWork方法中循环,我想,WorkerCompleted方法将永远不会被调用,因此从流中读取的值将永远不会被显示?感谢Tudor,非常感谢,我采用了您的方法,它完成了工作!您是否将WorkerSupportsScanCellation设置为true?抱歉,是的,应该注意,WorkerSupportsScanCellation和WorkerSupportsProgress都为true。
if (e.Cancelled || disconnectFlag)
{
disconnectFlag = false;
//close connection here
} else ...