/// <summary> /// This method is based upon increasing the MaxInfoFrames in the MSTP. /// In Bacnet/IP this will have bad effect due to the retries /// </summary> public void DownloadFileByAsync(BacnetClient comm, BacnetAddress adr, BacnetObjectId object_id, string filename, Action <int> progress_action) { Cancel = false; //open file System.IO.FileStream fs = null; try { fs = System.IO.File.OpenWrite(filename); } catch (Exception ex) { throw new System.IO.IOException("Couldn't open file", ex); } uint max_count = (uint)comm.GetFileBufferMaxSize(); BacnetAsyncResult[] transfers = new BacnetAsyncResult[50]; byte old_max_info_frames = comm.Transport.MaxInfoFrames; comm.Transport.MaxInfoFrames = 50; //increase max_info_frames so that we can occupy line more. This might be against 'standard' try { int position = 0; bool eof = false; while (!eof && !Cancel) { //start many async transfers for (int i = 0; i < transfers.Length; i++) { transfers[i] = (BacnetAsyncResult)comm.BeginReadFileRequest(adr, object_id, position + i * (int)max_count, max_count, false); } //wait for all transfers to finish int current = 0; int retries = comm.Retries; while (current < transfers.Length) { if (!transfers[current].WaitForDone(comm.Timeout)) { if (--retries > 0) { transfers[current].Resend(); continue; } else { throw new System.IO.IOException("Couldn't read file"); } } retries = comm.Retries; uint count; byte[] file_buffer; int file_buffer_offset; Exception ex; comm.EndReadFileRequest(transfers[current], out count, out position, out eof, out file_buffer, out file_buffer_offset, out ex); transfers[current] = null; if (ex != null) { throw ex; } if (count > 0) { //write to file fs.Position = position; fs.Write(file_buffer, file_buffer_offset, (int)count); position += (int)count; if (progress_action != null) { progress_action(position); } } current++; } } } finally { fs.Close(); comm.Transport.MaxInfoFrames = old_max_info_frames; } }