取消连续从网络流中读取的后台工作程序

时间:2012-02-15 11:05:14

标签: c# multithreading tcp backgroundworker client-side

我运行的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();
        }

    }
}

}

2 个答案:

答案 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 ...