public ImageProcessDataflow(Camera camera, int width, int height, IPEndPoint udpEndpoint, CancellationToken token) { var faceModelParams = new FaceModelParameters(AppDomain.CurrentDomain.BaseDirectory, true, false, false); frameProducer = camera.CameraType == CameraType.Webcam ? new WebcamFrameProducer(int.Parse(camera.Id), width, height) : (FrameProducer) new DirectShowFrameProducer(camera.Id, width, height); cameraFps = new FpsDetector(token); landmarkFps = new FpsDetector(token); detectedFps = new FpsDetector(token); udpSender = new UdpSender(udpEndpoint); landmarkExtractor = new LandmarkExtractor(faceModelParams); dataExtractor = new DataExtractor(faceModelParams); var cancellationDataFlowOptions = new DataflowBlockOptions { CancellationToken = token }; DetectedDataBroadcast = new BroadcastBlock <DetectedData>(f => f, cancellationDataFlowOptions); LandmarkDataBroadcast = new BroadcastBlock <LandmarkData>(f => f, cancellationDataFlowOptions); BitmapBroadcast = new BroadcastBlock <WriteableBitmap>(f => f, cancellationDataFlowOptions); FrameDataBroadcast = new BroadcastBlock <FrameData>(f => f, cancellationDataFlowOptions); var bitmapBlock = new TransformBlock <FrameData, WriteableBitmap>(frm => bitmapTransformer.ConvertToWritableBitmap(frm.Frame), new ExecutionDataflowBlockOptions { CancellationToken = token, BoundedCapacity = 1, TaskScheduler = TaskScheduler.FromCurrentSynchronizationContext() }); var landmarkBlock = new TransformBlock <FrameData, LandmarkData>(x => landmarkExtractor.DetectLandmarks(x), new ExecutionDataflowBlockOptions { CancellationToken = token, BoundedCapacity = 1, }); var dataDetectorBlock = new TransformBlock <LandmarkData, DetectedData>(ld => dataExtractor.ExtractData(ld), new ExecutionDataflowBlockOptions { CancellationToken = token, BoundedCapacity = 1 }); var udpBlock = new ActionBlock <DetectedData>(d => udpSender.SendPoseData(d.Pose), new ExecutionDataflowBlockOptions { CancellationToken = token, BoundedCapacity = 1 }); var executionDataFlowOptions = new ExecutionDataflowBlockOptions { CancellationToken = token }; var cameraFpsBlock = new ActionBlock <FrameData>(_ => cameraFps.AddFrame(), executionDataFlowOptions); var landmarkFpsBlock = new ActionBlock <LandmarkData>(_ => landmarkFps.AddFrame(), executionDataFlowOptions); var detectedFpsBlock = new ActionBlock <DetectedData>(_ => detectedFps.AddFrame(), executionDataFlowOptions); FrameDataBroadcast.LinkTo(bitmapBlock); FrameDataBroadcast.LinkTo(cameraFpsBlock); bitmapBlock.LinkTo(BitmapBroadcast); FrameDataBroadcast.LinkTo(landmarkBlock); landmarkBlock.LinkTo(LandmarkDataBroadcast); LandmarkDataBroadcast.LinkTo(landmarkFpsBlock); LandmarkDataBroadcast.LinkTo(dataDetectorBlock, l => l.DetectionSucceeded); dataDetectorBlock.LinkTo(DetectedDataBroadcast); DetectedDataBroadcast.LinkTo(detectedFpsBlock); DetectedDataBroadcast.LinkTo(udpBlock); //Start producing frames Task.Factory.StartNew(() => frameProducer.ReadFrames(FrameDataBroadcast), token, TaskCreationOptions.LongRunning, TaskScheduler.Default); }