private void AddItems(OperationInfo[] ops, int i = -1) { lvItems.BeginUpdate(); foreach(OperationInfo op in ops) { ListViewItem item = new ListViewItem(op.from); item.Tag = op; if (op.operation == Operation.Download) item.ImageIndex = 1; else item.ImageIndex = 0; ListViewItem.ListViewSubItem subitem = new ListViewItem.ListViewSubItem(item, op.to); item.SubItems.Add(subitem); subitem = new ListViewItem.ListViewSubItem(item, GetSizeText(op)); item.SubItems.Add(subitem); ProgressListview.ProgressSubItem progress = new ProgressListview.ProgressSubItem(item, GetStatusText(op)); progress.Owner = item; progress.ProgressMaxValue = op.totalSize; progress.ProgressValue = op.doneSize; progress.ShowProgress = false; progress.ForeColor = GetStatusColor(op); progress.Tag = op; op.Tag = progress; item.SubItems.Add(progress); if (i >= 0) lvItems.Items.Insert(i, item); else lvItems.Items.Add(item); Statistics(op, 1); } lvItems.EndUpdate(); }
public void Add(OperationInfo[] ops) { List<OperationInfo> pending_list = new List<OperationInfo>(); List<OperationInfo> processing_list = new List<OperationInfo>(); List<OperationInfo> completed_list = new List<OperationInfo>(); foreach(OperationInfo op in ops) { switch (op.status) { case OperationStatus.Pending: pending_list.Add(op); break; case OperationStatus.Processing: processing_list.Add(op); break; default: completed_list.Add(op); break; } } lock (locker) { pending.AddRange(pending_list); processing.AddRange(processing_list); completed.AddRange(completed_list); } if (OnAdd != null) OnAdd(this, new DUQueueEventArgs(ops)); }
public bool RestoreFrom(TextReader reader) { XmlDocument xml = new XmlDocument(); xml.Load(reader); XmlNodeList nodes = xml.SelectNodes("/items/item"); List<OperationInfo> list = new List<OperationInfo>(nodes.Count); foreach (XmlNode n in nodes) { OperationInfo op = new OperationInfo(); XmlAttribute attr; attr = n.Attributes["uid"]; op.uid = attr != null ? attr.Value : ""; attr = n.Attributes["operation"]; op.operation = attr != null ? (Operation)Enum.Parse(typeof(Operation), attr.Value) : Operation.Download; attr = n.Attributes["from"]; op.from = attr != null ? attr.Value : ""; attr = n.Attributes["to"]; op.to = attr != null ? attr.Value : ""; attr = n.Attributes["status"]; op.status = attr != null ? (OperationStatus)Enum.Parse(typeof(OperationStatus), attr.Value) : OperationStatus.Pending; attr = n.Attributes["errmsg"]; op.errmsg = attr != null ? attr.Value : ""; attr = n.Attributes["doneSize"]; op.doneSize = attr != null ? Convert.ToInt64(attr.Value) : 0; attr = n.Attributes["totalSize"]; op.totalSize = attr != null ? Convert.ToInt64(attr.Value) : 0; attr = n.Attributes["sliceFileName"]; op.sliceFileName = attr != null ? attr.Value : ""; list.Add(op); } worker.queue.Add(list.ToArray()); return true; }
private void du_onCompleted(object sender, CompletedEventArgs e) { IProgressable d = (IProgressable)sender; OperationInfo op = (OperationInfo)d.State; if (e.Success) { op.status = OperationStatus.Success; } else if (op.status == OperationStatus.Processing) { if (e.Cancel) { op.status = OperationStatus.Cancel; } else { op.status = OperationStatus.Fail; op.errmsg = e.Exception == null ? string.Empty : e.Exception.Message; } } }
private void du_onProgress(object sender, ProgressEventArgs e) { IProgressable d = (IProgressable)sender; OperationInfo op = (OperationInfo)d.State; op.totalSize = e.totalSize; op.doneSize = e.doneSize; fireOnProgress(op); if (op.status != OperationStatus.Processing) { e.Cancel = true; } else if (IsPause) { e.Cancel = true; op.status = OperationStatus.Pending; } else if (op.sid != Interlocked.Read(ref sid)) { e.Cancel = true; op.status = OperationStatus.Pending; } }
private void download(OperationInfo op) { Downloader d = null; PcsFileInfo from; try { fireOnProgress(op); // 触发一次进度改变 from = pcs.meta(op.from); if (from.IsEmpty) { op.status = OperationStatus.Fail; op.errmsg = "The remote file not exists (" + from.path + ")."; } else if (from.isdir) { op.status = OperationStatus.Fail; op.errmsg = "Can't download directory (" + from.path + ")."; } else if (op.status == OperationStatus.Processing) { op.totalSize = from.size; fireOnProgress(op); // 触发一次进度改变 //如果在进度处理程序中,改变了状态,则跳过继续处理 if (op.status == OperationStatus.Processing) { if (from.size > MultiThreadDownloader.MIN_SLICE_SIZE) d = new MultiThreadDownloader(pcs, from, op.to, workfolder, getDownloadMaxThreadCount(), getMinDownloadSliceSize()); else d = new Downloader(pcs, from, op.to); d.Completed += du_onCompleted; d.Progress += du_onProgress; d.StateFileNameDecide += du_onStateFileNameDecide; d.State = op; d.Download(); } } } catch (Exception ex) { op.status = OperationStatus.Fail; op.errmsg = ex.Message; } }
public DUQueueEventArgs(OperationInfo[] ops) { this.Operations = ops; }
private string GetSizeText(OperationInfo op) { switch (op.status) { case OperationStatus.Pending: return Utils.HumanReadableSize(op.doneSize) + "/" + Utils.HumanReadableSize(op.totalSize); case OperationStatus.Processing: return Utils.HumanReadableSize(op.doneSize) + "/" + Utils.HumanReadableSize(op.totalSize); case OperationStatus.Pause: return Utils.HumanReadableSize(op.doneSize) + "/" + Utils.HumanReadableSize(op.totalSize); case OperationStatus.Cancel: return Utils.HumanReadableSize(op.doneSize) + "/" + Utils.HumanReadableSize(op.totalSize); case OperationStatus.Success: return Utils.HumanReadableSize(op.totalSize); case OperationStatus.Fail: return Utils.HumanReadableSize(op.doneSize) + "/" + Utils.HumanReadableSize(op.totalSize); default: return string.Empty; } }
public DUWorkerEventArgs(OperationInfo op) { this.op = op; }
private void upload(OperationInfo op) { Uploader u = null; try { System.IO.FileInfo fi = new System.IO.FileInfo(op.from); op.totalSize = fi.Length; fireOnProgress(op); // 触发一次进度改变 //如果在进度处理程序中,改变了状态,则跳过继续处理 if (op.status == OperationStatus.Processing) { if (fi.Length > MultiThreadUploader.MIN_SLICE_SIZE) { u = new RapidUploader(pcs, op.from, op.to); u.Upload(); if (u.Success) op.status = OperationStatus.Success; else if (u.IsCancelled) op.status = OperationStatus.Cancel; else if (op.status == OperationStatus.Processing) u = new MultiThreadUploader(pcs, op.from, op.to, workfolder, getUploadMaxThreadCount()); else u = null; // op 的状态已经被改变,且不是 OperationStatus.Processing } else if (op.status == OperationStatus.Processing) u = new Uploader(pcs, op.from, op.to); else u = null; // op 的状态已经被改变,且不是 OperationStatus.Processing if (u != null && op.status == OperationStatus.Processing) { u.IsOverWrite = AppSettings.OverWriteWhenUploadFile; u.Progress += du_onProgress; u.Completed += du_onCompleted; u.StateFileNameDecide += du_onStateFileNameDecide; u.State = op; u.Upload(); } } } catch (Exception ex) { op.status = OperationStatus.Fail; op.errmsg = ex.Message; } }
private void UpdateProgress(OperationInfo op) { ProgressListview.ProgressSubItem progress = op.Tag as ProgressListview.ProgressSubItem; if (progress != null) { progress.ProgressMaxValue = op.totalSize; progress.ProgressValue = op.doneSize; progress.ForeColor = GetStatusColor(op); progress.ShowProgress = true; ListViewItem item = progress.Owner; if (item != null) item.SubItems[2].Text = GetSizeText(op); double percent = 0; if (op.totalSize > 0) { percent = (double)op.doneSize / (double)op.totalSize; if (percent > 1.0f) percent = 1.0f; } progress.Text = string.Format("{0}%", percent.ToString("F2")); item.EnsureVisible(); } }
private void Statistics(OperationInfo op, int i = 1) { switch (op.status) { case OperationStatus.Cancel: Interlocked.Add(ref cancelCount, i); break; case OperationStatus.Fail: Interlocked.Add(ref failedCount, i); break; case OperationStatus.Pause: Interlocked.Add(ref pauseCount, i); break; case OperationStatus.Pending: case OperationStatus.Processing: Interlocked.Add(ref pendingCount, i); break; case OperationStatus.Success: Interlocked.Add(ref successCount, i); break; } }
private void RemoveItems(OperationInfo[] ops) { lvItems.BeginUpdate(); foreach(OperationInfo op in ops) { ProgressListview.ProgressSubItem progress = op.Tag as ProgressListview.ProgressSubItem; if (progress != null && progress.Owner != null) { lvItems.Items.Remove(progress.Owner); } Statistics(op, -1); } lvItems.EndUpdate(); }
private string GetStatusText(OperationInfo op) { switch (op.status) { case OperationStatus.Pending: return "Pending"; case OperationStatus.Processing: return "Processing"; case OperationStatus.Pause: return "Pause"; case OperationStatus.Cancel: return "Cancel"; case OperationStatus.Success: return "Success"; case OperationStatus.Fail: return "Fail: " + op.errmsg; default: return string.Empty; } }
private Color GetStatusColor(OperationInfo op) { switch (op.status) { case OperationStatus.Pending: return Color.Black; case OperationStatus.Processing: return Color.Blue; case OperationStatus.Pause: return Color.Orange; case OperationStatus.Cancel: return Color.Gray; case OperationStatus.Success: return Color.Green; case OperationStatus.Fail: return Color.Red; default: return Color.Black; } }
private void fireOnCompleted(OperationInfo op) { if (OnCompleted != null) OnCompleted(this, new DUWorkerEventArgs(op)); }
private void fireOnProgress(OperationInfo op) { if (OnProgress != null) OnProgress(this, new DUWorkerEventArgs(op)); }
public bool Contains(OperationInfo op) { bool contains = false; lock (locker) { contains = pending.Contains(op); if (!contains) contains = processing.Contains(op); if (!contains) contains = completed.Contains(op); } return contains; }
public void Enqueue(OperationInfo[] ops) { lock (locker) { pending.AddRange(ops); } if (OnEnqueue != null) OnEnqueue(this, new DUQueueEventArgs(ops)); }
public void place(OperationInfo op) { bool removed = false; lock (locker) { switch (op.status) { case OperationStatus.Pending: if (!pending.Contains(op)) pending.Insert(0, op); removed = processing.Remove(op); if (!removed) removed = completed.Remove(op); break; case OperationStatus.Processing: if (!processing.Contains(op)) processing.Insert(0, op); removed = pending.Remove(op); if (!removed) removed = completed.Remove(op); break; default: if (!completed.Contains(op)) completed.Insert(0, op); removed = processing.Remove(op); if (!removed) removed = pending.Remove(op); break; } } }
public void Remove(OperationInfo op) { bool removed = false; lock (locker) { removed = pending.Remove(op); if (!removed) removed = processing.Remove(op); if (!removed) removed = completed.Remove(op); } if (removed && OnRemove != null) OnRemove(this, new DUQueueEventArgs(new OperationInfo[] { op })); try { if (!string.IsNullOrEmpty(op.sliceFileName)) { //删除分片数据 if (System.IO.File.Exists(op.sliceFileName)) System.IO.File.Delete(op.sliceFileName); } } catch { } }
private void execTask() { long csid = Interlocked.Read(ref sid); long tick = 0, ndirty; OperationInfo op = null; queue.Clear(); persister.Restore(); fireOnStart(); while (csid == Interlocked.Read(ref sid)) { #region 暂停 if (IsPause) { Thread.Sleep(100); continue; } #endregion #region 每 5 秒保存一次 ndirty = Interlocked.Read(ref dirty); if (tick > 50 && ndirty > 0) { persister.Save(); Interlocked.Add(ref dirty, -ndirty); tick = 0; } else { tick++; } #endregion #region 获取待处理的 OperationInfo 对象 op = queue.Dequeue(); if (op == null) { Thread.Sleep(100); continue; } else if (op.status != OperationStatus.Pending && op.status != OperationStatus.Processing) // 来自中断后还原 { queue.place(op); continue; } #endregion #region 处理 OperationInfo 对象 op.sid = csid; op.status = OperationStatus.Processing; queue.place(op); //如果在进度处理程序中,改变了状态,则跳过继续处理 if (op.operation == Operation.Download) { download(op); //如果 download() 方法中未设置状态,则设置状态为失败 if (op.status == OperationStatus.Processing) { op.errmsg = "Unknow error"; op.status = OperationStatus.Fail; } } else if (op.operation == Operation.Upload) { upload(op); //如果 upload() 方法中未设置状态,则设置状态为失败 if (op.status == OperationStatus.Processing) { op.errmsg = "Unknow error"; op.status = OperationStatus.Fail; } } else { //未知的操作类型,直接设置状态为失败 op.errmsg = "Unknow operation"; op.status = OperationStatus.Fail; } queue.place(op); Interlocked.Increment(ref dirty); #endregion fireOnCompleted(op); } Interlocked.Exchange(ref status, 0); persister.Save(); Interlocked.Exchange(ref dirty, 0); queue.Clear(); fireOnStop(); }
private void ChangeOpStatus(OperationInfo op, OperationStatus status) { Statistics(op, -1); op.status = status; Statistics(op, 1); worker.queue.place(op); ProgressListview.ProgressSubItem progress = op.Tag as ProgressListview.ProgressSubItem; if (progress != null) { progress.ForeColor = GetStatusColor(op); progress.Text = GetStatusText(op); } }