首页 文章

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

提问于
浏览
0

我有一个运行的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

    你能不能在后台工作者方法中循环?

    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线程 .

  • 0

    您似乎在worker complete方法中调用RunWorkerAsync()并重置CancellationPending prop . 我想你可以尝试通过添加Disconnect()方法解决这个问题一些disconnectFlag = true;在WorkerComplete方法中,您应该添加:

    if (e.Cancelled || disconnectFlag)
        {
            disconnectFlag = false;
            //close connection here
        } else ...
    

相关问题