/// <summary> /// Loops until it gets a new assignment and sends it to the RenderClient (or all assignments have been rendered) /// </summary> public void TryToGetNewAssignment() { while (Master.singleton.finishedAssignments < Master.singleton.totalNumberOfAssignments - assignmentsAtClients) { if (!NetworkSupport.IsConnected(client)) { LostConnection(); return; } Master.singleton.availableAssignments.TryDequeue(out Assignment newAssignment); if (!Master.singleton.progressData.Continue) // test whether rendering should end (Stop button pressed) { return; } if (newAssignment == null) // TryDequeue was not succesfull { continue; } lock (stream) { NetworkSupport.SendObject(newAssignment, stream); assignmentsAtClients++; unfinishedAssignments.Add(newAssignment); } break; } }
/// <summary> /// Asynchronous image receiver uses NetworkStream.ReadAsync /// Recursively called at the end /// If so, it reads it as - expected format is array of floats /// - first 2 floats represents x1 and y1 coordinates - position in main bitmap; /// - rest of array are colors of rendered bitmap - 3 floats (RGB values) per pixel; /// - stored per lines from left upper corner (coordinates position) /// </summary> public async void ReceiveRenderedImageAsync() { while (Master.singleton.finishedAssignments < Master.singleton.totalNumberOfAssignments && Master.singleton.progressData.Continue) { if (!NetworkSupport.IsConnected(client)) { LostConnection(); return; } byte[] receiveBuffer = new byte[bufferSize]; try { await stream.ReadAsync(receiveBuffer, 0, bufferSize, imageReceivalCancelToken); } catch (IOException) { LostConnection(); return; } // Uses parts of receiveBuffer - separates and converts data to coordinates // and floats representing colors of pixels float[] coordinates = new float[2]; float[] floatBuffer = new float[Master.assignmentSize * Master.assignmentSize * 3]; Buffer.BlockCopy(receiveBuffer, 0, coordinates, 0, 2 * sizeof(float)); Buffer.BlockCopy(receiveBuffer, 2 * sizeof(float), floatBuffer, 0, floatBuffer.Length * sizeof(float)); Master.singleton.BitmapMerger( floatBuffer, (int)coordinates[0], (int)coordinates[1], (int)coordinates[0] + Master.assignmentSize, (int)coordinates[1] + Master.assignmentSize); Master.singleton.finishedAssignments++; // Takes care of increasing assignmentRoundsFinished by the amount of finished // rendering rounds on RenderClient. lock (unfinishedAssignments) { Assignment currentAssignment = unfinishedAssignments.Find(a => a.x1 == (int)coordinates[0] && a.y1 == (int)coordinates[1]); int roundsFinished = (int)Math.Log(currentAssignment.stride, 2) + 1; // stride goes from 8 > 4 > 2 > 1 (1 step = 1 rendering round) Master.singleton.assignmentRoundsFinished += roundsFinished; assignmentsAtClients--; RemoveAssignmentFromUnfinishedAssignments((int)coordinates[0], (int)coordinates[1]); } TryToGetNewAssignment(); } }