private TransferTracker CreateTransferTracker() { bool visibility = this.Visible; FormWindowState ws = this.WindowState; int width = 0; if (tpfiles.Controls.Count == 0) { width = tpfiles.Width - 3; } else { width = tpfiles.Controls[0].Width; } this.WindowState = FormWindowState.Normal; if (!this.Visible && this.Opacity == 100) { this.Opacity = 0; this.Visible = true; } tcMain.SelectedIndex = 1; TransferTracker tt = new TransferTracker(); tt.gb = new GroupBox() { Name = "gbFileTransfer" + tpfiles.Controls.Count.ToString(), Width = width, Height = 40, Top = tpfiles.Controls.Count * 40 + 10, Text = "Transferring file: " + tpfiles.Controls.Count.ToString(), Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right }; tt.pb = new ProgressBar() { Width = width - 12, Height = 10, Top = 20, Left = 7, Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right }; tt.gb.Controls.Add(tt.pb); tpfiles.Controls.Add(tt.gb); this.WindowState = ws; this.Visible = visibility; return(tt); }
private void TransferFiles(String sourceFolder, String baseFolder, String targetPath, String filter = "*.*", int speed = 1000, int filesAtOnce = 5) { cancel = false; String[] files = GetFiles(sourceFolder, filter, SearchOption.AllDirectories); String xferId = ""; List <String> thislist = new List <String>(); Object fileLocker = new Object(); long totalNumFiles = files.Length; Dictionary <String, int> tries = new Dictionary <String, int>(); bool complete = false; bool skippedLast = false; long threadsStarted = 0; int skipLatency = 0; int fileCopyLatency = 0; thislist.AddRange(files); UI(() => { pbTransfer.Minimum = 0; pbTransfer.Maximum = (int)totalNumFiles; xferId = tbUniqueId.Text.Trim(); int.TryParse(tbSkipLatency.Text.Trim(), out skipLatency); int.TryParse(tbFileCopyLatency.Text.Trim(), out fileCopyLatency); tpfiles.Controls.Clear(); lbErrorMsgs.Items.Clear(); }); Func <String> getFile = () => { String thisFile = ""; lock (fileLocker) { if (thislist.Count > 0) { thisFile = thislist[0]; thislist.RemoveAt(0); } } return(thisFile); }; UI(() => lblStatus.Text = "Attempting to connect to the server ( Transfer Session 1 )"); try { if (xferClient != null) { try { xferClient.Close(); } catch (Exception) { } } Thread.Sleep(500); xferClient = new Tools.FileTransfer.Client(remoteServerPort, remoteServerAddress.ToString(), xferId); xferClient.Connect(); new Thread(() => { while (running && !complete) { if (!xferClient.Connected()) { try { xferClient.Close(); } catch (Exception) { Thread.Sleep(100); } try { xferClient.Connect(); } catch (Exception) { Thread.Sleep(100); } } else { Thread.Sleep(1); } } }).Start(); } catch (Exception ex) { if (ex.Message.Equals("")) { UI(() => lblStatus.Text = "The remote file transfer server could not be contacted."); } else { UI(() => lblStatus.Text = ex.Message); } running = false; return; } lock (clientsLocker) { clients.Add(xferClient); } // Create a WaitTimeout that watches for these threads to report complete: WaitTimeout threadWaiter = null; ThreadPool.QueueUserWorkItem((o) => { // wait as long as 24 hours (or until all worker threads report in): threadWaiter = new WaitTimeout(86400000, () => { return(!running); }); threadWaiter.WaitOn(filesAtOnce, false); // Release the main thread: complete = true; // Wait for the connection monitor to exit... try { Thread.Sleep(500); } catch (Exception) { } // Preform cleanup: clients.Clear(); xferClient.Close(); }); for (int count = 0; count < filesAtOnce; count++) { ThreadPool.QueueUserWorkItem((o) => { int numDisConnects = 0; String streamName = "TransferDataStream " + ((int)o).ToString() + numDisConnects.ToString(); bool reportedStarted = false; String thisFile = getFile(); FileTransfer.Client.Transfer thisTransfer = xferClient.CreateNewTransfer((String msg) => { UI(() => { if (msg.Contains("not been modified")) { msg = msg.Replace("Transfer Failed", "Skipped"); } lblStatus.Text = msg; try { try { pbTransfer.Value = (int)(totalNumFiles - thislist.Count); gbOverallProgress.Text = "Over all progress: " + ((int)(totalNumFiles - thislist.Count)).ToString() + @"/" + totalNumFiles.ToString(); } catch (Exception) { } } catch (Exception) { } }); }); // Create the TransferTracker Thread: new Thread(() => { TransferTracker tt = null; bool ttCreated = false; UI(() => { tt = CreateTransferTracker(); tt.pb.Maximum = 100; tt.pb.Value = 0; ttCreated = true; }); while (!ttCreated) { Thread.Sleep(1); } double percent = 0; String trackedFile = ""; while (running && !thisFile.Equals("") && !cancel && !complete) { lock (fileLocker) { trackedFile = thisFile; } if (!trackedFile.Equals("") && thisTransfer.IsComplete() == false) { UI(() => { if (!tt.gb.Text.Equals(Path.GetFileName(trackedFile)) && !tt.gb.Text.Equals("")) { tt.gb.Text = Path.GetFileName(trackedFile); tt.pb.Value = 0; } percent = thisTransfer.BytesWritten(); percent = (percent / thisTransfer.length) * 100; if (percent > -1 && percent < 100) { if (tt.pb.Value != (int)percent) { tt.pb.Value = (int)percent; } } }); } else { UI(() => { if (tt.pb.Value != 100) { tt.pb.Value = 100; } }); } Thread.Sleep(25); } UI(() => tt.pb.Value = 100); }).Start(); // Send files while (!thisFile.Equals("") && !cancel) { try { if (!xferClient.Connected() && !complete) { while (xferClient.Connected() == false && running && !cancel && !complete) { Thread.Sleep(1); } } // Speed throttling - important for controling CPU usage. if (skippedLast) { Thread.Sleep(skipLatency); skippedLast = false; } else { Thread.Sleep(fileCopyLatency); } // Send this file, and block until it completes: if (!thisTransfer.Send(thisFile, baseFolder, targetPath, streamName, speed, true)) { // If our transfer failed for any other reason then that the target file is identical... if (!thisTransfer.errMsg.ToLower().Contains("not been modified")) { // Sleep here for a short time to make sure we don't cause a dissconnection due to // bandwidth starvation: throw new Exception(thisTransfer.errMsg); } else { skippedLast = true; } } } catch (Exception ex) { UI(() => { lbErrorMsgs.Items.Add(streamName + ": " + ex.Message); }); if (ex.Message.Contains("connection lost") || ex.Message.Contains("target corrupt")) { lock (fileLocker) { // Add it to the end so that there is time for it to be closed properly: thislist.Add(thisFile); numDisConnects += 1; streamName = "TransferDataStream " + ((int)o).ToString() + numDisConnects.ToString(); } } } if (!reportedStarted) { Interlocked.Increment(ref threadsStarted); reportedStarted = true; } if (Interlocked.Read(ref threadsStarted) < filesAtOnce) { Thread.Sleep(100); } thisFile = getFile(); } // Give things a change to finieh Thread.Sleep(1000); threadWaiter.ReportThreadComplete(); }, count); } // We need to block until this all completes: while (!complete && running) { Thread.Sleep(1); } UI(() => { lblStatus.Text = "Transfer complete."; }); }