protected override void OnProgressUpdate(params InterfaceViewModel[] values) { base.OnProgressUpdate(values); foreach (InterfaceViewModel interfaceViewModel in values) { ProgressUpdated?.Invoke(this, new ProgressUpdatedEventArgs(interfaceViewModel)); } }
private void RemoveAllEventHandels() { lock (this) { if (NewClientConnected != null) { var del = NewClientConnected.GetInvocationList(); for (int i = 0; i < del.Length; i++) { NewClientConnected -= del[i] as Action <IRemoteXTMF>; } } if (NewClientConnected != null) { var del = NewClientConnected.GetInvocationList(); for (int i = 0; i < del.Length; i++) { NewClientConnected -= del[i] as Action <IRemoteXTMF>; } } if (ClientDisconnected != null) { var del = ClientDisconnected.GetInvocationList(); for (int i = 0; i < del.Length; i++) { ClientDisconnected -= del[i] as Action <IRemoteXTMF>; } } if (ProgressUpdated != null) { var del = ProgressUpdated.GetInvocationList(); for (int i = 0; i < del.Length; i++) { ProgressUpdated -= del[i] as Action <IRemoteXTMF, float>; } } if (ClientRunComplete != null) { var del = ClientRunComplete.GetInvocationList(); for (int i = 0; i < del.Length; i++) { ClientRunComplete -= del[i] as Action <IRemoteXTMF, int, string>; } } if (AllModelSystemRunsComplete != null) { var del = AllModelSystemRunsComplete.GetInvocationList(); for (int i = 0; i < del.Length; i++) { AllModelSystemRunsComplete -= del[i] as Action; } } RemoveAll(_CustomHandlers); RemoveAll(_CustomReceivers); RemoveAll(_CustomSenders); } }
public void ErrorOutputHandler(object sendingProcess, DataReceivedEventArgs outLine) { ProgressUpdated?.Invoke(outLine.Data); if (Abort) { ((Process)sendingProcess).Kill(); Abort = false; } }
protected virtual void OnProgressUpdated(DownloadProgressChangedEventArgs e) { var dlItem = (DownloadItem)e.UserState; dlItem.BytesRecived = e.BytesReceived; dlItem.TotalBytes = e.TotalBytesToReceive; dlItem.ProgressPrecentage = e.ProgressPercentage; ProgressUpdated?.Invoke(this, e); }
private void DLCompletedCallback(object sender) { // Try to download the next item in the queue, if applicable if (totalDownloads != 0) { completionPercentage = ((totalDownloads - dlQueue.Count) / (double)totalDownloads) * 100; ProgressUpdated.Invoke(this); } DownloadNext(); }
public async Task Start(CancellationToken token) { for (var i = 0; i < 100; i++) { token.ThrowIfCancellationRequested(); await Task.Delay(1000); Progress++; ProgressUpdated?.Invoke(this, EventArgs.Empty); } }
public Task <DownloadFile> Download(CancellationToken token, ProgressUpdated updateProgressAction = null) { SetupDownloadRequest(); if (updateProgressAction != null) { OnUpdateProgress = updateProgressAction; } return(Task.Factory.FromAsync( Request.BeginGetResponse, asyncResult => Request.EndGetResponse(asyncResult), null ).ContinueWith(t => HandleResponse(t.Result, token), token)); }
private void ReportProgress(Match match) { long GetBytes(double size, string units) { int GetMultiplier() { switch (units) { case "KiB": return(1024); case "MiB": return(1024 * 1024); case "GiB": return(1024 * 1024 * 1024); default: throw new InvalidOperationException("Invalid units for multiplier."); } } return((long)(size * GetMultiplier())); } long?GetDownloadSpeed() { string downloadSpeed = match.Groups["DownloadSpeed"].Value; if (downloadSpeed == string.Empty) { return(null); } return(GetBytes(double.Parse(downloadSpeed), match.Groups["DownloadSpeedUnits"].Value)); } long totalDownloadSize = GetBytes(double.Parse(match.Groups["TotalDownloadSize"].Value), match.Groups["TotalDownloadSizeUnits"].Value); double progressPercentage = double.Parse(match.Groups["ProgressPercentage"].Value); if (_stage == 0 || progressPercentage >= 100 && _lastProgress < 100) { ++_stage; } _lastProgress = progressPercentage; ProgressUpdated?.Invoke(this, new ProgressUpdatedEventArgs(totalDownloadSize, progressPercentage, GetDownloadSpeed(), _stage)); }
private void ProgressMonitor() { long lastPosition = Position; while (true) { if (Position != 0) { ProgressUpdated?.Invoke(Status.Downloading, (double)Position / Length * 100, Position - lastPosition); } lastPosition = Position; Thread.Sleep(1000); } }
public void StartGettingFilesDescriptors() { var files = GetMp3FilesRecursively(_path).ToList(); for (int i = 0; i < files.Count; i++) { var filePath = files[i]; FileTemplate item = new FileTemplate(filePath); item.Mp3Length = GetMp3Length(filePath); NewFileParsed?.Invoke(this, item); ProgressUpdated?.Invoke(this, GetProgress(i + 1, files.Count)); } }
public override void Handle(string pLine) { if (pLine.StartsWith("Current Frame:", StringComparison.CurrentCulture)) { var arrParts = pLine.Split(','); if (arrParts.Length > 0) { int?intFrame = null; int?intPercentage = null; foreach (string strPart in arrParts) { var arrKvp = strPart.Split(':'); if (arrKvp.Length == 2) { var strKey = arrKvp[0].Trim(); switch (strKey) { case "Current Frame": int intTmpFrame; if (int.TryParse(arrKvp[1].Trim(), out intTmpFrame)) { intFrame = intTmpFrame; } break; case "percentage": int intTmpPercentage; if (int.TryParse(arrKvp[1].Trim(), out intTmpPercentage)) { intPercentage = intTmpPercentage; } break; } } } if (intFrame != null && intPercentage != null && _intPrevPercentage != intPercentage) { _intPrevPercentage = (int)intPercentage; Log.Info("Progress Changed, notify world"); ProgressUpdated?.Invoke(this, new EventArgs.ProgressUpdatedEventArgs((int)intFrame, (int)intPercentage)); } } } }
public void DownloadLatest() { ProgressUpdated?.Invoke(Status.Initializing, 0, 0); File.Move(Filepath, Filepath + ".backup"); IsBackuped = true; string downloadUrl = GetLatestDownloadUrl(); ProgressUpdated?.Invoke(Status.Downloading, 0, 0); StartProgressMonitor(); Download(Filepath, downloadUrl); AbortProgressMonitor(); ProgressUpdated?.Invoke(Status.Finishing, 100, 0); File.Delete(Filepath + ".backup"); ProgressUpdated?.Invoke(Status.Finished, 100, 0); IsRunning = false; Finished?.Invoke(); }
void ProcessFile(string path) { FileInfo info = new FileInfo(path); FolderInfoDictionary[info.Directory.FullName].size += info.Length; FolderInfoDictionary[info.Directory.FullName].FileCount++; SizeOfProcessedFiles += info.Length; double percentCompleted = (SizeOfProcessedFiles / (double)SizeOfDrive) * 100; //Update the UI on the main thread Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() => { //Every 0.5 percent done raise ProgressUpdated if (percentCompleted > PercentDone + 0.5) { PercentDone = (SizeOfProcessedFiles / (double)SizeOfDrive) * 100; ProgressUpdated?.Invoke(null, new ProgressUpdatedEventArgs(PercentDone)); } })); }
private void UpdateProgress() { if (!UnknownTotalMode && Progress.Total < 1L) { SetUnknownTotalMode(); } if (NumericMode) { BytesProgressValue.Text = Progress.Current.ToString(); BytesTotalValue.Text = Progress.Total.ToString(); } else if (!PercentageMode) { BytesProgressValue.Text = ConvertBytesSep(Progress.Current, out string Unit); BytesProgress.Text = Unit; SpeedValue.Text = Progress.GetSpeed(out Unit); Speed.Text = Unit; } if (!UnknownTotalMode) { double Ratio = Progress.Ratio, Angle = 6.283185307179586D * Ratio; ElementBorder.Fill = new SolidColorBrush(FromRgb((byte)(21D + 139D * Ratio), (byte)(21D + 79D * Ratio), (byte)(21D * (1D - Ratio)))); if (Ratio == 1D) { Angle -= 0.0000001D; } Arc.IsLargeArc = Angle > PI; Arc.Point = new Point(HalfWidth + (HalfWidth - 7D) * Sin(Angle), HalfHeight - (HalfHeight - 7D) * Cos(Angle)); if (!NumericMode) { if (!PercentageMode) { BytesTotalValue.Text = ConvertBytesSep(Progress.Total, out string Unit); BytesTotal.Text = Unit; } Percentage.Text = Progress.Total > 104857600L ? Progress.PrecisePercentage : Progress.Percentage; } } ProgressUpdated?.Invoke(); }
public static async Task SyndDataAsync(IContainerProvider container) { Barrel.Current.EmptyAll(); var interfaces = Assembly.GetExecutingAssembly() .GetTypes() .Where(x => x.IsInterface && typeof(ISyncService).IsAssignableFrom(x) && x != typeof(IService <>) && x != typeof(ISyncService)) .ToArray(); for (int index = 0; index < interfaces.Length; index++) { try { var service = (ISyncService)container.Resolve(interfaces[index]); if (service == null) { continue; } await service.SyncAsync(); if (ProgressUpdated != null) { double progress = (index + 1) / (double)interfaces.Length; ProgressUpdated.Invoke(progress, new EventArgs()); } } catch (Exception) { // TODO - log error } } var settings = new Settings { LastUpdated = DateTime.UtcNow }; Barrel.Current.Add(nameof(Settings), settings, TimeSpan.FromDays(5)); }
public static async Task Read(IList <StorageFolder> folder, IList <string> filterdFolderNames) { var list = new List <StorageFile>(); int i = 1; var scan = Consts.Localizer.GetString("FolderScanText"); foreach (var item in folder) { var files = await GetFilesAsync(item, filterdFolderNames); var opr = SQLOperator.Current(); if (KnownFolders.MusicLibrary.Path == item.Path || item.Path.Contains(ApplicationData.Current.LocalFolder.Path)) { } else { await opr.UpdateFolderAsync(item, files.Count); } list.AddRange(files); ProgressUpdated?.Invoke(null, new ProgressReport() { Description = SmartFormat.Smart.Format(scan, i, folder.Count), Current = i, Total = folder.Count }); i++; } await Task.Delay(200); ProgressUpdated?.Invoke(null, new ProgressReport() { Description = Consts.Localizer.GetString("FolderScanFinishText"), Current = i, Total = folder.Count }); await Task.Delay(200); await ReadFileandSave(from a in list group a by a.Path into b select b.First()); }
/// <summary> /// Start route crawling /// </summary> /// <returns></returns> public void Start() { Task t = Task.Run(async() => { // If route directory exists if (Directory.Exists(RoutePath)) { try { // Counts size of all files AllFilesSize = CountAllFiles(); // Find all dependencies await GetDependencies(); } catch (Exception e) { if (e.GetType() != typeof(ThreadInterruptedException) && e.GetType() != typeof(ThreadAbortException)) { Trace.Assert(false, string.Format(Localization.Strings.CrawlingRouteFail, RoutePath), e.ToString()); } } // If crawling skipped because cache or inaccuracy, adds to 100 % if (PercentProgress != 100) { DeltaProgress?.Invoke(100f - PercentProgress); PercentProgress = 100; ProgressUpdated?.Invoke(PercentProgress); } } // Crawling complete event Complete?.Invoke(); }); }
public async Task Read(IList <StorageFolder> folder) { var list = new List <StorageFile>(); int i = 1; foreach (var item in folder) { var files = await GetFilesAsync(item); var opr = SQLOperator.Current(); if (KnownFolders.MusicLibrary.Path == item.Path || item.Path == ApplicationData.Current.LocalFolder.Path) { } else { await opr.UpdateFolderAsync(item, files.Count); } list.AddRange(files); ProgressUpdated?.Invoke(this, new ProgressReport() { Description = $"{i} of {folder.Count} folders scanned", Current = i, Total = folder.Count }); i++; } await Task.Delay(200); ProgressUpdated?.Invoke(this, new ProgressReport() { Description = "Folder scanning completed", Current = i, Total = folder.Count }); await Task.Delay(200); await ReadFileandSave(from a in list group a by a.Path into b select b.First()); }
/// <summary> /// Invokes all registerd callbacks /// </summary> /// <param name="value"></param> public void Report(Tuple <int, string> value) => ProgressUpdated?.Invoke(this, value);
private void OnAngerUpdated() { progressBar.BarValue = Anger; ProgressUpdated?.Invoke(Anger); }
private void OnProgressUpdated(Double progress) { ProgressUpdated?.Invoke(progress); }
/// <summary> /// Fires the progress updated event. /// </summary> private static void UpdateProgress(string message, int progressValue, int progressMax) { ProgressUpdated?.Invoke(message, progressValue, progressMax); }
/// <summary> /// Enumerates GCRoots of a given object. Similar to !gcroot. /// </summary> /// <param name="target">The target object to search for GC rooting.</param> /// <param name="unique">Whether to only return fully unique paths.</param> /// <param name="maxDegreeOfParallelism">The number of threads this class is allowed to use to calculate the result. /// Setting this to 1 will cause the algorithm to run on the current thread.</param> /// <param name="roots">The roots to consider. You can pass ClrMD.</param> /// <param name="cancellationToken">A cancellation token to stop enumeration.</param> /// <returns>An enumeration of all GC roots found for target.</returns> public IEnumerable <GCRootPath> EnumerateGCRoots(ulong target, bool unique, int maxDegreeOfParallelism, IEnumerable <IClrRoot> roots, CancellationToken cancellationToken = default) { if (roots is null) { throw new ArgumentNullException(nameof(roots)); } bool parallel = Heap.Runtime.IsThreadSafe && maxDegreeOfParallelism > 1; Dictionary <ulong, LinkedListNode <ClrObject> > knownEndPoints = new Dictionary <ulong, LinkedListNode <ClrObject> >() { { target, new LinkedListNode <ClrObject>(Heap.GetObject(target)) } }; if (!parallel) { int count = 0; ObjectSet processedObjects = new ObjectSet(Heap); foreach (IClrRoot root in roots) { LinkedList <ClrObject> path = PathsTo(processedObjects, knownEndPoints, root.Object, target, unique, cancellationToken).FirstOrDefault(); if (path != null) { yield return(new GCRootPath(root, path.ToImmutableArray())); } if (count != processedObjects.Count) { count = processedObjects.Count; ProgressUpdated?.Invoke(this, count); } } } else { ParallelObjectSet processedObjects = new ParallelObjectSet(Heap); ConcurrentQueue <GCRootPath> results = new ConcurrentQueue <GCRootPath>(); using BlockingCollection <IClrRoot?> queue = new BlockingCollection <IClrRoot?>(); Thread[] threads = new Thread[Math.Min(maxDegreeOfParallelism, Environment.ProcessorCount)]; for (int i = 0; i < threads.Length; i++) { threads[i] = new Thread(() => WorkerThread(queue, results, processedObjects, knownEndPoints, target, all: true, unique, cancellationToken)) { Name = "GCRoot Worker Thread" }; threads[i].Start(); } foreach (IClrRoot root in roots) { queue.Add(root); } // Add one sentinal value for every thread for (int i = 0; i < threads.Length; i++) { queue.Add(null); } int count = 0; // Worker threads end when they have run out of roots to process. While we are waiting for them to exit, yield return // any results they've found. We'll use a 100 msec timeout because processing roots is slooooow and finding a root is // rare. There's no reason to check these results super quickly and starve worker threads. for (int i = 0; i < threads.Length; i++) { while (!threads[i].Join(100)) { while (results.TryDequeue(out GCRootPath result)) { yield return(result); } } if (count != processedObjects.Count) { count = processedObjects.Count; ProgressUpdated?.Invoke(this, count); } } // We could have raced to put an object in the results queue while joining the last thread, so we need to drain the // results queue one last time. while (results.TryDequeue(out GCRootPath result)) { yield return(result); } if (count != processedObjects.Count) { count = processedObjects.Count; ProgressUpdated?.Invoke(this, count); } } }
protected virtual void OnProgressUpdated(ProgressUpdatedEventArgs e) => ProgressUpdated?.Invoke(this, e);
public static async Task ReadFileandSave(IEnumerable <StorageFile> files) { var opr = SQLOperator.Current(); var total = files.Count(); int i = 1; var newlist = new List <SONG>(); var durationFilter = Settings.Current.FileDurationFilterEnabled; var duration = Convert.ToInt32(Settings.Current.FileDurationFilter); var scan = Consts.Localizer.GetString("FileReadText"); var oneDriveFailed = false; foreach (var file in files.OrderBy(f => f.Path)) { try { if (!file.IsAvailable || file.Attributes.HasFlag(FileAttributes.LocallyIncomplete)) { if (file.Provider.Id != "OneDrive" || oneDriveFailed || !Settings.Current.OnedriveRoaming) { continue; } try { var oneDriveFile = await OneDrivePropertyProvider.GetOneDriveFilesAsync(file.Path); var properties = oneDriveFile.OneDriveItem; var audioProp = properties.Audio; if (durationFilter && audioProp.Duration < duration) { continue; } var artist = audioProp?.Artist is null ? null : new[] { audioProp.Artist }; var composers = audioProp?.Composers is null ? null : new[] { audioProp.Composers }; var song = await Song.Create(null, file.Path, (audioProp?.Title, audioProp?.Album, artist, artist, composers, null, TimeSpan.FromMilliseconds(audioProp?.Duration ?? 0), (uint)(audioProp?.Bitrate * 1000 ?? 0), 0), null, oneDriveFile); var t = await opr.InsertSongAsync(song); if (t != null) { newlist.Add(t); } } catch { // Prevent another try by next file. oneDriveFailed = true; // Will be handled by outer catch block. throw; } } else { using (var tagTemp = File.Create(file.Path)) { var prop = await file.Properties.GetMusicPropertiesAsync(); var d = prop.Duration.Milliseconds < 1 ? tagTemp.Properties.Duration : prop.Duration; if (durationFilter && d.Milliseconds < duration) { continue; } var song = await Song.Create(tagTemp.Tag, file.Path, await file.GetViolatePropertiesAsync(), tagTemp.Properties, null); var t = await opr.InsertSongAsync(song); if (t != null) { newlist.Add(t); } } } } catch (Exception e) { Shared.Helpers.Tools.Logging(e); continue; } finally { ProgressUpdated?.Invoke(null, new ProgressReport() { Description = SmartFormat.Smart.Format(scan, i, total), Current = i, Total = total }); i++; } } await RemoveDuplicate(); await SortAlbums(); Completed?.Invoke(null, EventArgs.Empty); }
private bool ProcessMessage(bool done, RemoteXTMF ourRemoteClient, BinaryWriter writer, BinaryFormatter converter, Message message) { if (message != null) { //If we have a message to process, process it switch (message.Type) { case MessageType.Quit: { done = true; } break; case MessageType.RequestProgress: { writer.Write((Int32)MessageType.RequestProgress); writer.Flush(); } break; case MessageType.RequestResource: { var name = message.Data as string; writer.Write((Int32)MessageType.ReturningResource); writer.Write(name); if (Resources.TryGetValue(name, out object data)) { writer.Write(true); converter.Serialize(writer.BaseStream, data); } else { writer.Write(false); } writer.Flush(); } break; case MessageType.PostComplete: { CompletedTask(ourRemoteClient, 0, String.Empty); } break; case MessageType.PostCancel: { writer.Write((Int32)MessageType.PostCancel); writer.Flush(); } break; case MessageType.PostProgess: { var progress = (float)message.Data; ourRemoteClient.Progress = progress; // we need to lock here since other clients could also // be trying to update the host with their progress lock (this) { try { ProgressUpdated?.Invoke(ourRemoteClient, progress); } catch { } } } break; case MessageType.PostResource: { var data = (ResourcePost)message.Data; Resources[data.Name] = data.Data; } break; case MessageType.SendModelSystem: { writer.Write((Int32)MessageType.SendModelSystem); var mss = message.Data as IModelSystemStructure; try { byte[] data = null; using (MemoryStream memStream = new MemoryStream()) { mss.Save(memStream); memStream.Position = 0; data = memStream.ToArray(); } writer.Write(data.Length); writer.Write(data, 0, data.Length); } catch (Exception e) { Console.WriteLine(e.ToString()); } writer.Flush(); } break; case MessageType.SendCustomMessage: { var msg = message.Data as SendCustomMessageMessage; int msgNumber = msg.CustomMessageNumber; int length = 0; var failed = false; byte[] buffer = null; if (_CustomSenders.TryGetValue(msgNumber, out Action <object, IRemoteXTMF, Stream> customConverter)) { using (MemoryStream mem = new MemoryStream(0x100)) { try { customConverter(msg.Data, ourRemoteClient, mem); mem.Position = 0; buffer = mem.ToArray(); length = buffer.Length; } catch { failed = true; } } } writer.Write((int)MessageType.SendCustomMessage); writer.Write((int)msg.CustomMessageNumber); writer.Write((Int32)length); if (!failed) { writer.Write(buffer, 0, length); buffer = null; } } break; case MessageType.ReceiveCustomMessage: { var msg = message.Data as ReceiveCustomMessageMessage; var customNumber = msg.CustomMessageNumber; if (_CustomReceivers.TryGetValue(customNumber, out Func <Stream, IRemoteXTMF, object> customConverter)) { using (var stream = msg.Stream) { try { object output = customConverter(stream, ourRemoteClient); if (_CustomHandlers.TryGetValue(msg.CustomMessageNumber, out List <Action <object, IRemoteXTMF> > handlers)) { foreach (var handler in handlers) { try { handler(output, ourRemoteClient); } catch { } } } } catch { } } } } break; default: { done = true; } break; } } return(done); }
private static void Process() { Console.WriteLine("Processing Started"); Delivery currentDeliveryStart = deliveryList[0]; ShowDeliveryData?.Invoke(); IdUpdated?.Invoke(currentDeliveryStart.Id); while (deliveryList.Count != 0) { timer.Start(); Delivery currentDelivery = deliveryList[0]; DeliveryService.EvaluatePriorities(ElapsedTime); RemoveDeliveryData?.Invoke(); IdUpdated?.Invoke(currentDelivery.Id); ShowDeliveryData?.Invoke(); Console.WriteLine($"Delivering ID: {currentDelivery.Id}"); //double additionalTimeFactor; //if (currentDelivery.PackageType == PackageType.Mini) //{ // additionalTimeFactor = 1; //} //else if (currentDelivery.PackageType == PackageType.Standaard) //{ // additionalTimeFactor = 1.2; //} //else //{ // additionalTimeFactor = 1.5; //} int waitTimeMilliseconds = (int)(((currentDelivery.TravelTime)) * 100); double timeFactor = (double)3.6 * ((currentDelivery.TravelTime) / (double)10); double progressValue = ((double)10 / ((double)waitTimeMilliseconds)) * 2; //GUI freezes //Task deliveryThread = Task.Run(() => Deliver(elapsedTime, waitTimeMilliseconds)); //deliveryThread.Wait(waitTimeMilliseconds); //Task remainingTimeThread = Task.Run(() => RemainingTime(elapsedTime, waitTimeMilliseconds)); //remainingTimeThread.Wait(waitTimeMilliseconds); //GUI freezes while (timer.ElapsedMilliseconds < waitTimeMilliseconds) { string currentInfo = "Pakket is onderweg!"; int elapsedTime = (int)timer.ElapsedMilliseconds; int remainingTime = (waitTimeMilliseconds - elapsedTime); ProgressUpdated?.Invoke(currentInfo, progressValue, remainingTime); } Console.WriteLine($"Finished ID {currentDelivery.Id} in {currentDelivery.TravelTime} min"); deliveryList.RemoveAt(0); RefreshList?.Invoke(); RemoveDeliveryData?.Invoke(); IdUpdated?.Invoke(currentDelivery.Id); ShowDeliveryData?.Invoke(); timer.Reset(); timer.Stop(); } string packageGone = "Er is geen pakket onderweg."; ProgressUpdated?.Invoke(packageGone, 0, 0); RemoveDeliveryData?.Invoke(); Console.WriteLine("Processing Stopped"); Processing = false; }
/// <summary> /// Updates the UI of the solution runner with the current progress, and schedules the next update a couple of /// milliseconds in the future. /// </summary> protected Task UpdateProgressAsync() { _myUpdateTick = Environment.TickCount + MillisecondsBetweenProgressUpdates; ProgressUpdated?.Invoke(this, new SolutionProgressEventArgs(Progress)); return(Task.Delay(1, CancellationToken)); }
private void LogAndUpdate(string msg, int itemsComplete, int totalItems) { Logger?.Write($"[{DateTime.Now}] {msg}"); ProgressUpdated?.Invoke(new ProgressUpdateEventArgs(msg, itemsComplete, totalItems)); }
// Static Methods private static void OnProgressUpdated(ModbusPoller instance, ProgressUpdate update) { ProgressUpdated?.Invoke(instance, new EventArgs <ProgressUpdate>(update)); }