用任务/异步/等待替换后台工作者?

时间:2020-03-19 12:58:21

标签: c# .net sockets task

我的代码当前实现了两个后台工作程序,一个用于TX,一个用于RX。两者都是异步运行的。

发送7字节TX命令后,我将收到7字节RX响应。

如果可能的话,我想将接收字节任务链接为发送字节任务,因为这似乎很合逻辑。

我知道后台工作人员已经过时,并且想通过使用Task-Parallel-Library使代码现代化。

有人可以阐明如何用异步任务替换所描述的上下文的backgroundWorker_DoWork事件处理程序吗?

这是一些代码:

    public static class MyService
    {
        public static byte[] binarySend, binaryReceive;
        public static string receive, send;
        public static BinaryReader binaryReader;
        public static BinaryWriter binaryWriter;
        public static TcpClient tcpClient;
        public static StreamReader streamReader;
        public static StreamWriter StreamWriter;
        public static NetworkStream NetworkStream;
        public static bool expReply, expAck = false;
        public static string ipAddress = "someIP";
        public static string portNo = "somePort";
        public static double currentZoomPos;
        public static BackgroundWorker backgroundWorkerRX, backgroundWorkerTX; 


        public static void ConnectCamera()
        {
            tcpClient = new TcpClient();
            backgroundWorkerRX = new BackgroundWorker();
            try
            {
                IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse(ipAddress), int.Parse(port));
                tcpClient.Connect(endPoint);

                if (tcpClient.Connected)
                {
                    Console.WriteLine($"Connected to {ipAddress} port: {port}");
                    NetworkStream networkStream = tcpClient.GetStream();
                    binaryWriter = new BinaryWriter(networkStream);
                    binaryReader = new BinaryReader(networkStream);
                    // background worker1 
                    backgroundWorkerRX.RunWorkerAsync(); //-- start RX
                    backgroundWorkerRX.WorkerSupportsCancellation = true;
                }
            }
            catch (Exception ex) {Console.WriteLine("serial connection failed.");}
        }

        public static void QueryZoom()
        {
            // Send query zoom command via client using binary writer
            var tx_data = new byte[7] { 0xff, 0x01, 0x00, 0x55, 0x00, 0x00, 0x56};
            expReply = true;
            binarySend = tx_data;
            backgroundWorkerTX.RunWorkerAsync();
        }

        // RX data
        public static void backgroundWorkerRX_DoWork(object sender, DoWorkEventArgs e) 
        {
            if(backgroundWorkerRX.CancellationPending == true) {backgroundWorkerRX.CancelAsync();}

            while (tcpClient.Connected)
            {
                try
                {
                    if (expReply)
                    {
                        // What I need to return -- 
                        binaryReceive = binaryReader.ReadBytes(7);
                        {
                            if (binaryReceive[0] == 0xFF && binaryReceive[1] == 0x01)
                            {
                                if(binaryReceive[3] == 0x5D)
                                {
                                    currentZoomPos = (binaryReceive[4] * 256) + binaryReceive[5];
                                    Console.WriteLine($"Current Zoom position is: {currentZoomPos}");
                                }
                            }
                            binaryReceive = null;
                        }
                        expReply = false;
                    }
                }
                catch (Exception ex) {Console.WriteLine(ex.Message.ToString());}
            }
        }

        //TX data
        public static void backgroundWorkerTX_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                if (tcpClient.Connected)
                {
                    if (binarySend != null)
                    {
                        binaryWriter.Write(binarySend);
                        binarySend = null;
                    }
                }
            }
            catch (Exception ex) {Console.WriteLine(ex.Message.ToString());}
        }
    }

1 个答案:

答案 0 :(得分:1)

如果您始终总是先发送字节,然后再接收字节,则可以使用以下内容:

public static class NetworkStreamExtensions
{
    public static async Task<byte[]> SendReceiveBytes(this NetworkStream self, byte[] toSend, int bytesToReceive, CancellationToken cancel)
    {
        await self.WriteAsync(toSend, 0, toSend.Length, cancel);
        var receiveBuffer = new byte[bytesToReceive];
        var receivedBytes = await self.ReadAsync(receiveBuffer, 0, receiveBuffer.Length, cancel);

        if (receivedBytes != receiveBuffer.Length)
        {
            // Handle incorrect number of received bytes, 
        }

        return receiveBuffer;
    }
}

由于正在使用async / await,它将使用当前同步上下文来运行代码。即如果在主线程上调用,它将在主线程上发送和接收。但是,由于异步方法不会阻止执行,因此它将允许在编写和读取之间运行其他代码。

相关问题