Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.BackgroundProcessing/3.2/WorkerMonitor.cs @ 2408

Last change on this file since 2408 was 2408, checked in by swagner, 15 years ago

Corrected minor code formatting issues (#769)

File size: 4.2 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.ComponentModel;
6using System.Threading;
7using System.Collections.ObjectModel;
8using System.Collections.Specialized;
9using System.Collections;
10
11namespace HeuristicLab.BackgroundProcessing {
12  /// <summary>
13  /// Provides a list of all currently running or pending ObservableBackgroundWorkers.
14  /// </summary>
15  public class WorkerMonitor : ObservableEnumerable<ObservableBackgroundWorker> {
16    public static WorkerMonitor Default = new WorkerMonitor();
17
18    public event ThreadExceptionEventHandler ThreadException;
19    public event NotifyCollectionChangedEventHandler CollectionChanged;
20
21    private List<ObservableBackgroundWorker> BackgroundWorkers;
22    private ReaderWriterLockSlim workerLock;
23
24    public WorkerMonitor() {
25      BackgroundWorkers = new List<ObservableBackgroundWorker>();
26      workerLock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
27    }
28
29    internal void RegisterWorker(ObservableBackgroundWorker worker) {
30      worker.RunWorkerCompleted += worker_RunWorkerCompleted;
31      worker.WorkerStopped += worker_WorkerStopped;
32      try {
33        workerLock.EnterUpgradeableReadLock();
34        try {
35          workerLock.EnterWriteLock();
36          BackgroundWorkers.Add(worker);
37        } finally {
38          workerLock.ExitWriteLock();
39        }
40        int index = BackgroundWorkers.Count - 1;
41        OnCollectionChanged(new NotifyCollectionChangedEventArgs(
42          NotifyCollectionChangedAction.Add, worker, index));
43      } finally {
44        workerLock.ExitUpgradeableReadLock();
45      }
46    }
47
48    void worker_WorkerStopped(object sender, EventArgs e) {
49      ObservableBackgroundWorker worker = sender as ObservableBackgroundWorker;
50      try {
51        workerLock.EnterUpgradeableReadLock();
52        int index = BackgroundWorkers.IndexOf(worker);
53        try {
54          workerLock.EnterWriteLock();
55          BackgroundWorkers.RemoveAt(index);
56        } finally {
57          workerLock.ExitWriteLock();
58        }
59        OnCollectionChanged(new NotifyCollectionChangedEventArgs(
60          NotifyCollectionChangedAction.Remove, worker, index));
61      } finally {
62        workerLock.ExitUpgradeableReadLock();
63      }
64    }
65
66    private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
67      ObservableBackgroundWorker worker = sender as ObservableBackgroundWorker;
68      if (e.Error != null) {
69        OnThreadException(new Exception(worker.Name, e.Error));
70      }
71    }
72
73    protected void OnThreadException(Exception x) {
74      if (ThreadException != null)
75        ThreadException(this, new ThreadExceptionEventArgs(x));
76    }
77
78    public IEnumerator<ObservableBackgroundWorker> GetEnumerator() {
79      try {
80        workerLock.EnterReadLock();
81        IList<ObservableBackgroundWorker> copy = BackgroundWorkers.ToList();
82        return copy.GetEnumerator();
83      } finally {
84        workerLock.ExitReadLock();
85      }
86    }
87
88    IEnumerator IEnumerable.GetEnumerator() {
89      return GetEnumerator();
90    }
91
92    protected void OnCollectionChanged(NotifyCollectionChangedEventArgs args) {
93      if (CollectionChanged != null)
94        CollectionChanged(this, args);
95    }
96
97    public void CancelAll() {
98      List<ObservableBackgroundWorker> cancelableWorkers = GetCancelableWorkers();
99      lock (cancelableWorkers) {
100        foreach (var worker in cancelableWorkers.ToList()) {
101          worker.WorkerStopped += (sender, args) => {
102            lock (cancelableWorkers) {
103              cancelableWorkers.Remove((ObservableBackgroundWorker)sender);
104              Monitor.Pulse(cancelableWorkers);
105            }
106          };
107          worker.CancelAsync();
108          if (!worker.IsRunning)
109            cancelableWorkers.Remove(worker);
110        }
111        while (cancelableWorkers.Count > 0)
112          Monitor.Wait(cancelableWorkers);
113      }
114    }
115
116    private List<ObservableBackgroundWorker> GetCancelableWorkers() {
117      try {
118        workerLock.EnterReadLock();
119        return BackgroundWorkers.Where(w => w.WorkerSupportsCancellation).ToList();
120      } finally {
121        workerLock.ExitReadLock();
122      }
123    }
124  }
125}
Note: See TracBrowser for help on using the repository browser.