internal BackgroundWorker( ITransport transport, BackgroundWorkerOptions options, CancellationTokenSource cancellationTokenSource = null, IProducerConsumerCollection <SentryEvent> queue = null) { Debug.Assert(transport != null); Debug.Assert(options != null); _inSemaphore = new SemaphoreSlim(options.MaxQueueItems, options.MaxQueueItems); _outSemaphore = new SemaphoreSlim(0, options.MaxQueueItems); _options = options; _cancellationTokenSource = cancellationTokenSource ?? new CancellationTokenSource(); _queue = queue ?? new ConcurrentQueue <SentryEvent>(); WorkerTask = Task.Run( async() => await WorkerAsync( _queue, _options, transport, _inSemaphore, _outSemaphore, _cancellationTokenSource.Token) .ConfigureAwait(false)); }
} // FillGrid private void AsyncGetEpgPrograms(BackgroundWorkerOptions options, IBackgroundWorkerDialog dialog) { IEpgLinkedList servicePrograms; dialog.SetProgressText("Requesting data for channels..."); LocalReferenceTime = DateTime.Now; var programs = Datastore.GetAllPrograms(LocalReferenceTime, 0, 2); dialog.SetProgressText("Sorting information..."); var index = -1; foreach (var service in ServicesList) { index++; // TODO: do NOT assume .imagenio.es var fullServiceName = service.ServiceName + ".imagenio.es"; var fullAlternateServiceName = service.ReplacementService?.ServiceName + ".imagenio.es"; if (!programs.TryGetValue(fullServiceName, out servicePrograms)) { if (!programs.TryGetValue(fullAlternateServiceName, out servicePrograms)) { continue; } // if } // if EpgPrograms[index] = servicePrograms; } // foreach } // AsyncGetEpgPrograms
private static async Task WorkerAsync( BlockingCollection <SentryEvent> queue, BackgroundWorkerOptions options, ITransport transport, CancellationToken cancellation) { var shutdownTimeout = new CancellationTokenSource(); var shutdownRequested = false; while (!shutdownTimeout.IsCancellationRequested) { // If the cancellation was signaled, // set the latest we can keep reading off the queue (while there's still stuff to read) if (!shutdownRequested && cancellation.IsCancellationRequested) { shutdownTimeout.CancelAfter(options.ShutdownTimeout); shutdownRequested = true; } if (queue.TryTake(out var @event)) { try { // Optionally we can keep multiple requests in-flight concurrently: // instead of awaiting here, keep reading from the queue while less than // N events are being sent await transport.CaptureEventAsync(@event, shutdownTimeout.Token).ConfigureAwait(false); } catch (Exception exception) { // TODO: Notify error handler Debug.WriteLine(exception.ToString()); } } else { if (shutdownRequested) { break; // Shutdown requested and queue is empty. ready to quit. } // Queue is empty, wait asynchronously before polling again try { await Task.Delay(options.EmptyQueueDelay, cancellation).ConfigureAwait(false); } // Cancellation requested, scheduled shutdown but loop again in case there are more items catch (OperationCanceledException) { shutdownTimeout.CancelAfter(options.ShutdownTimeout); shutdownRequested = true; } } } }
} // RecordTasksDialog_Shown private void AsyncBuildList(BackgroundWorkerOptions options, IBackgroundWorkerDialog dialog) { var result = options.OutputData as AsyncResult; if (dialog.QueryCancel()) { return; } dialog.SetProgressText(TasksTexts.ObtainingTasks); result.taskList = TaskList.Build(new TaskListBuildOptions() { RecordTaskFolder = RecordTaskFolder, SchedulerFolders = SchedulerFolders, ScanAllWindowsSchedulerTasks = true, AddAllWindowsSchedulerTaks = true, }); if (dialog.QueryCancel()) { return; } dialog.SetProgressText(TasksTexts.CreatingTasksList); var q = from task in result.taskList where task.Status == TaskStatus.Ok select task; var items = new List <ListViewItem>(result.taskList.Count); foreach (var task in q) { var channelName = (task.Task != null) ? task.Task.Channel.Name : null; var name = (task.Task != null) ? task.Name : task.SchedulerName; var item = new ListViewItem(channelName); item.SubItems.Add(name); if (task.Task == null) { item.SubItems.Add(TasksTexts.TaskNameUnknown); } else { item.SubItems.Add(ToString(task.Task.Schedule.Kind)); } // if-else item.SubItems.Add(task.NumberOfRecordings == null ? TasksTexts.RecordingsUnknown : task.NumberOfRecordings.Value.ToString(Application.CurrentCulture)); item.Tag = task; items.Add(item); } // foreach result.items = items.ToArray(); } // AsyncBuildList
public SdkComposer(SentryOptions options) { _options = options ?? throw new ArgumentNullException(nameof(options)); if (options.Dsn == null) { throw new ArgumentException("No DSN defined in the SentryOptions"); } var httpOptions = new HttpOptions(options.Dsn.SentryUri); options.ConfigureHttpTransportOptions?.Invoke(httpOptions); _httpOptions = httpOptions; var workerOptions = new BackgroundWorkerOptions(); options.ConfigureBackgroundWorkerOptions?.Invoke(workerOptions); _workerOptions = workerOptions; }
} // constructor #region Event handlers private void EpgBasicGridDialog_Load(object sender, EventArgs e) { BasicGoogleTelemetry.SendScreenHit(this); EpgPrograms = new IEpgLinkedList[ServicesList.Count]; ChangeSelectedRow(-1); var workerOptions = new BackgroundWorkerOptions() { OutputData = EpgPrograms, BackgroundTask = AsyncGetEpgPrograms, AfterTask = FillGrid, AllowAutoClose = true, TaskDescription = Properties.Texts.EpgDataLoadingList, AllowCancelButton = true, }; var result = BackgroundWorkerDialog.RunWorkerAsync(this, workerOptions); var close = false; if (workerOptions.OutputException != null) { HandleException(new ExceptionEventData(Properties.Texts.ObtainingListException, workerOptions.OutputException)); close = true; } // if if (result != DialogResult.OK) { close = true; } // if if (close) { Visible = false; Close(); } // if } // EpgBasicGridDialog_Load
public BackgroundWorker( ITransport transport, BackgroundWorkerOptions options) : this(transport, options, null, null) { }
} // dataGridPrograms_SelectionChanged #endregion private void FillGrid(BackgroundWorkerOptions options, IBackgroundWorkerDialog dialog) { if (dialog.QueryCancel()) { return; } dialog.SetProgressText("Filling the list..."); var serviceRowIndex = -1; foreach (var service in ServicesList) { var name = UiBroadcastListManager.GetColumnData(service, UiBroadcastListColumn.NumberAndName); var rowIndex = dataGridPrograms.Rows.Add(name); if (service.Key == InitialService?.Key) { serviceRowIndex = rowIndex; } // if // TODO: use ListManager view options for hidden and inactive programs (to show or no to show) if ((service.IsHidden) || (service.IsInactive)) { dataGridPrograms.Rows[rowIndex].DefaultCellStyle.ForeColor = SystemColors.GrayText; } // if } // foreach for (int index = 0; index < EpgPrograms.Length; index++) { int cellIndex; var row = dataGridPrograms.Rows[index]; var node = EpgPrograms[index]?.Requested; cellIndex = 1; while ((node != null) && (cellIndex < 4)) { var cell = row.Cells[cellIndex]; cell.Style.Alignment = DataGridViewContentAlignment.MiddleLeft; cell.Value = node.Program.Title; node = node.Next; cellIndex++; } // while // mark remaining cells as empty for (; cellIndex < 4; cellIndex++) { var cell = row.Cells[cellIndex]; cell.Style.ForeColor = SystemColors.GrayText; cell.Value = Properties.Texts.EpgNoInformationShort; cell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter; } // for cellIndex } // for index SelectedService = null; IsGridReady = true; if (serviceRowIndex >= 0) { dataGridPrograms.CurrentCell = dataGridPrograms.Rows[serviceRowIndex].Cells[1]; } else { SelectedRowIndex = -1; } // if-else } // FillGrid
private static BackgroundWorker CreateBackgroundWorker( ITransport transport, BackgroundWorkerOptions options) => new BackgroundWorker(transport, options);
private static async Task WorkerAsync( IProducerConsumerCollection <SentryEvent> queue, BackgroundWorkerOptions options, ITransport transport, SemaphoreSlim inSemaphore, SemaphoreSlim outSemaphore, CancellationToken cancellation) { var shutdownTimeout = new CancellationTokenSource(); var shutdownRequested = false; try { while (!shutdownTimeout.IsCancellationRequested) { // If the cancellation was signaled, // set the latest we can keep reading off of the queue (while there's still stuff to read) // No longer synchronized with outSemaphore (Enqueue will throw object disposed), // run until the end of the queue or shutdownTimeout if (!shutdownRequested) { try { await outSemaphore.WaitAsync(cancellation).ConfigureAwait(false); } // Cancellation requested, scheduled shutdown but continue in case there are more items catch (OperationCanceledException) { if (options.ShutdownTimeout == TimeSpan.Zero) { return; } else { shutdownTimeout.CancelAfter(options.ShutdownTimeout); } shutdownRequested = true; } } if (queue.TryTake(out var @event)) { inSemaphore.Release(); try { // Optionally we can keep multiple requests in-flight concurrently: // instead of awaiting here, keep reading from the queue while less than // N events are being sent await transport.CaptureEventAsync(@event, shutdownTimeout.Token).ConfigureAwait(false); } catch (OperationCanceledException) { // Shutdown token triggered. Time to exit. return; } catch (Exception exception) { // TODO: Notify error handler Debug.WriteLine(exception.ToString()); } } else { Debug.Assert(shutdownRequested); // Empty queue. Exit. return; } } } finally { inSemaphore.Dispose(); outSemaphore.Dispose(); } }