/// <summary>
        /// Sends a message indicating whether this agent is able to execute the job.
        /// If this agent is able, starts capturing images as configured in the given render job.
        /// </summary>
        /// <param name="jobRequest">The render job to execute.</param>
        private void HandleJobRequest(RCS_Render_Job jobRequest)
        {
            // check if this agent is able to execute the render job
            if (!this.CheckExecutionAbility(jobRequest))
            {
                return;
            }

            ScreenCapture capturer = new ScreenCapture();
            capturer.OnImageCaptured += Capturer_OnImageCaptured;
            capturer.OnCaptureFinished += Capturer_OnCaptureFinished;
            capturer.OnProcessExited += Capturer_OnProcessExited;

            lock (this.runningRenderJobs)
            {
                this.runningRenderJobs.Add(jobRequest.Configuration.RenderJobID, capturer);
            }

            try
            {
                capturer.StartCapture(jobRequest.Configuration);
            }
            catch (Exception ex)
            when (ex is InvalidOperationException ||
                  ex is ArgumentException ||
                  ex is ProcessStartupException)
            {
            }
        }
        /// <summary>
        /// Checks if this agent is able to execute the given render job and sends an according message to the client.
        /// </summary>
        /// <param name="renderJob">The render job to execute</param>
        /// <returns>True if this agent is able to execute the job, false otherwise.</returns>
        private bool CheckExecutionAbility(RCS_Render_Job renderJob)
        {
            bool capable = false;
            RCS_Render_Job_Message msg = null;
            IResource resource = renderJob.Configuration.JobToDo.Resource;

            if (renderJob == null ||
                renderJob.Configuration == null ||
                renderJob.Configuration.JobToDo == null)
            {
                return false;
            }

            if (resource is FileResource)
            {
                // check if a program exists which can open the file
                string filepath = ((FileResource)resource).Path;
                capable = ProgramFinder.FindExecutable(filepath) != string.Empty;
            }
            else if (resource is ProcessResource)
            {
                // check if process with given ID is running
                int pid = ((ProcessResource)resource).ProcessID;

                try
                {
                    Process.GetProcessById(pid);
                    capable = true;
                }
                catch
                {
                }
            }
            else
            {
                throw new NotSupportedException("Only FileResource and ProcessResource are supported.");
            }

            if (capable)
            {
                msg = new RCS_Render_Job_Message(RenderMessage.Supported, renderJob.Id, RemoteType.Agent);
            }
            else
            {
                msg = new RCS_Render_Job_Message(RenderMessage.NotSupported, renderJob.Id, RemoteType.Agent);
            }
            
            try
            {
                this.SendMessage(MessageCode.MC_Render_Job_Message, msg);
            }
            catch
            {
            }

            return capable;
        }
        public async Task<RenderMessage> Connect(Agent agent)
        {
            Client c = new Client();
            StreamSocket socket;

            try
            {
                socket = await c.Connect(agent.IP, NetworkConfiguration.PortAgent, CONNECT_TIMEOUT);
            }
            catch (Exception)
            {
                throw new AgentNotReachableException("The agent could not be found!");
            }

            // send render job request
            RCS_Render_Job jobRequest = new RCS_Render_Job(this.Configuration, RemoteType.Client);

            byte[] sendData = Remote_Content_Show_MessageGenerator.GetMessageAsByte(jobRequest);

            this.socketHandler = new SocketHandler(socket);

            this.socketHandler.SendMessage(MessageCode.MC_Render_Job, sendData);

            // receive render job response
            SocketHandler.SocketMessage socketMsg;
            socketMsg.Code = MessageCode.MC_Alive;
            socketMsg.Content = new byte[] { };
            socketMsg.Empty = true;

            socketMsg = await this.socketHandler.WaitForMessage();

            // if he sends some invalid data, give him another chance.
            if (!socketMsg.Empty && socketMsg.Code != MessageCode.MC_Render_Job_Message)
            {
                socketMsg = await this.socketHandler.WaitForMessage();
            }

            if (!socketMsg.Empty)
            {
                RCS_Render_Job_Message jobResponse = Remote_Content_Show_MessageGenerator.GetMessageFromByte<RCS_Render_Job_Message>(socketMsg.Content);

                if (jobResponse.Message == RenderMessage.Supported)
                {
                    this.Agent = agent;
                    //this.socketHandler = new SocketHandler(socket);

                    this.socketHandler.OnMessageBytesReceived += SocketHandler_OnMessageBytesReceived;
                    this.socketHandler.OnConnectionLost += SocketHandler_OnConnectionLost;
                    this.socketHandler.Start();

                    this.Working = true;

                    this.lastKeepAlive = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
                    this.KeepAlive();
                }

                return jobResponse.Message;
            }

            // okay, he is not able to communicate.
            this.socketHandler.Close();

            return RenderMessage.NotSupported;
        }