【问题标题】:How to correct cancel Task with Event Handler如何使用事件处理程序更正取消任务
【发布时间】:2017-07-14 17:16:54
【问题描述】:

抱歉英语不好。在我的项目中,我有两个任务。一种用于解码来自 IP 摄像机的数据并将帧就绪事件发送到 UI。和其他观看相机不离线。 如果相机离线,它会向 UI 线程抛出错误事件处理程序。 UI线程调用方法Stop Camera。但任务并没有停止。我做错了什么?

在按钮点击事件上它的工作完美。

        void BtnCamera_Click(object sender, EventArgs e)
    {
        if (cameraStream.FrameDecoderActive)
        {
            cameraStream.StopCameraPreview();
        }
        else
        {
            Task.Factory.StartNew(() => { cameraStream.StartCameraPreview();});
        }
    }

停止相机方法:

public void StopCameraPreview()
  {
   //cancel token source
   StopFrameDecoding.Cancel();
   StopFrameChecker.Cancel();
 }

这是我的第一个任务代码:

private void Run(Stream cameraStream)
    {
        try
        {
            FrameDecoderActive = true;
            //inicializacija
            Extensions Extensions = new Extensions();
            BinaryReader streamReader = new BinaryReader(cameraStream);
            byte[] imageBuffer = new byte[1024 * 1024];
            byte[] curentBuffer = streamReader.ReadBytes(readSize);

            //kadru skaitymas
            while (FrameDecoderActive)
            {
                StopFrameDecoding.Token.ThrowIfCancellationRequested();
                int imageStart = Extensions.Find(curentBuffer, jpegHeader);
                if (imageStart != -1)
                {
                    //randa jpg pradžia kameros streme
                    int size = curentBuffer.Length - imageStart;

                    //copy nuo jpg pradžio iki buferio galo į image buferį
                    Array.Copy(curentBuffer, imageStart, imageBuffer, 0, size);

                    //skaito kadrus kol gauna cancel tokeną
                    while (FrameDecoderActive)
                    {
                        curentBuffer = streamReader.ReadBytes(readSize);
                        int imageEnd = Extensions.Find(curentBuffer, boundaryBytes);

                        //jeigu neranda jpg pabaigos nuskaitytame buferyje
                        if (imageEnd != -1)
                        {
                            Array.Copy(curentBuffer, 0, imageBuffer, size, imageEnd);
                            size += imageEnd;

                            //naujas kadras
                            byte[] frame = new byte[size];
                            Array.Copy(imageBuffer, 0, frame, 0, size);
                            LastFrameTime = DateTime.Now;
                            if (!FrameCheckerActive)
                            {
                                StopFrameChecker = new CancellationTokenSource();
                                Task.Factory.StartNew(() => { FrameChecker(); }, StopFrameChecker.Token);
                            }
                            FrameReady.Invoke(this, new FrameReadyEventArgs { FrameBuffer = frame, Bitmap = BitmapFactory.DecodeByteArray(frame, 0, frame.Length) });

                            //kopijuojam buferio likuti i buferio pradzia
                            Array.Copy(curentBuffer, imageEnd, curentBuffer, 0, curentBuffer.Length - imageEnd);
                            //uzpildom likusia tuscia vieta
                            byte[] temp = streamReader.ReadBytes(imageEnd);
                            Array.Copy(temp, 0, curentBuffer, curentBuffer.Length - imageEnd, temp.Length);
                            break;
                        }

                        Array.Copy(curentBuffer, 0, imageBuffer, size, curentBuffer.Length);
                        size += curentBuffer.Length;
                    }
                }
            }
        }
        catch (OperationCanceledException)
            {
                Error.Invoke(this, new ErrorEventArgs { ErrorCode = 101, Message = "Camera decoder Canceled" });
            }
        catch (Exception ex)
            {
                Error.Invoke(this, new ErrorEventArgs { ErrorCode = 999, Message = ex.Message });
            }
        cameraStream.Close();
        FrameDecoderActive = false;
        Error.Invoke(this, new ErrorEventArgs { ErrorCode = 0, Message = "Camera Stoped" });
    }

第二个任务:

private async void FrameChecker()
    {
        FrameCheckerActive = true;
        await Task.Delay(1000);
        try
        {
            while (FrameDecoderActive)
            {
                StopFrameChecker.Token.ThrowIfCancellationRequested();
                DateTime curentTime = DateTime.Now;
                var dif = curentTime - LastFrameTime;
                if (dif.Seconds > 2)
                {
                    throw new TimeoutException("Camera Frame timeout");
                }
                await Task.Delay(1000);
            }
        }
        catch (TimeoutException)
        {
            Error.Invoke(this, new ErrorEventArgs { ErrorCode = 100, Message = "Camera Frame Timeout" });
        }
        catch (OperationCanceledException)
        {
            Error.Invoke(this, new ErrorEventArgs { ErrorCode = 101, Message = "Frame Checker Canceled"});
        }
        catch (Exception ex)
        {
            Error.Invoke(this, new ErrorEventArgs { ErrorCode = 999, Message = ex.Message});
        }
        FrameCheckerActive = false;
    }

【问题讨论】:

    标签: c# task cancellationtokensource cancellation-token


    【解决方案1】:

    您的嵌套循环妨碍了您。在您的第一个任务中,基本上:

    while (FrameDecoderActive)
    {
        StopFrameDecoding.Token.ThrowIfCancellationRequested();
    
        // some other stuff
    
        while (FrameDecoderActive)
        {
            // more stuff
            // never checks for cancellation!
        }
    }
    

    问题是内部循环从不调用StopFrameDecoding.Token.ThrowIfCancellationRequested()。因此,一旦代码进入该内部循环,它就不再检查是否请求取消。

    【讨论】:

    • 您好,感谢您的回复。我把它放在两个循环中。不工作。但是当找到图像结束时内部循环中断,然后检查是否抛出取消并开始搜索图像。
    【解决方案2】:
       while (FrameDecoderActive)
       {
       //checking if cacelation thrown
       StopFrameDecoding.Token.ThrowIfCancellationRequested();
    
      //Search image start on buffer readed from camera stream
    
    
       while (FrameDecoderActive)
       {
      // read while found image end then break
       }
       }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-13
      • 2020-08-17
      • 1970-01-01
      • 1970-01-01
      • 2012-06-15
      • 2016-08-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多