我运行的TCP服务器会定期发出2个字节的消息。
我正在尝试创建一个连接到服务器的客户端表单,并从流中连续读取,直到我单击表单上的断开连接按钮。
到目前为止,客户端工作正常,但我无法断开连接。我将CancellationPending设置为true,但在dowork方法有机会设置e.Cancel之前,它似乎重置为false。
我也确定必须有一种更可接受的方式来连续读取流并写入表单 - 目前我在Worker Completed方法中调用RunWorkerAsync来实现循环!
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();
}
}
}
}
答案 0 :(得分:0)
你不能只在后台工作方法中循环吗?
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;
}
}
}
然后在断开连接时只需关闭插座。这将导致Exception
在while循环中抛出,您可以优雅地退出catch
块。
Edit
:然后,您可以在读取每条消息后从循环更新GUI。确保您正在更新的控件的句柄可用(假设它被称为box
):
delegate void updateDelegate(String p);
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);
box.BeginInvoke(new updateDelegate(writeToBox), reply);
}
catch (Exception ex)
{
return;
}
}
}
在这种情况下需要 BeginInvoke
,因为您尝试从另一个线程更新GUI,这是不允许的。此方法将更新转发到GUI线程。
答案 1 :(得分:0)
您似乎在worker complete方法中调用RunWorkerAsync()并重置CancellationPending prop。我想你可以尝试通过添加Disconnect()方法解决这个问题一些disconnectFlag = true;在WorkerComplete方法中,您应该添加:
if (e.Cancelled || disconnectFlag)
{
disconnectFlag = false;
//close connection here
} else ...