Маршаллинг событий в разных потоках
Я полагаю, что это может быть отмечено как повторяющееся и закрытое, но я не могу на всю жизнь найти четкий, краткий ответ на этот вопрос. Все ответы и ресурсы касаются почти исключительно форм Windows Forms и использования предварительно созданных служебных классов, таких как BackgroundWorker. Мне бы очень хотелось понять эту концепцию в ее основе, чтобы я мог применить фундаментальные знания к другим реализациям потоков.
Простой пример того, чего я хотел бы достичь:
//timer running on a seperate thread and raising events at set intervals
//incomplete, but functional, except for the cross-thread event raising
class Timer
{
//how often the Alarm event is raised
float _alarmInterval;
//stopwatch to keep time
Stopwatch _stopwatch;
//this Thread used to repeatedly check for events to raise
Thread _timerThread;
//used to pause the timer
bool _paused;
//used to determine Alarm event raises
float _timeOfLastAlarm = 0;
//this is the event I want to raise on the Main Thread
public event EventHandler Alarm;
//Constructor
public Timer(float alarmInterval)
{
_alarmInterval = alarmInterval;
_stopwatch = new Stopwatch();
_timerThread = new Thread(new ThreadStart(Initiate));
}
//toggles the Timer
//do I need to marshall this data back and forth as well? or is the
//_paused boolean in a shared data pool that both threads can access?
public void Pause()
{
_paused = (!_paused);
}
//little Helper to start the Stopwatch and loop over the Main method
void Initiate()
{
_stopwatch.Start();
while (true) Main();
}
//checks for Alarm events
void Main()
{
if (_paused && _stopwatch.IsRunning) _stopwatch.Stop();
if (!_paused && !_stopwatch.IsRunning) _stopwatch.Start();
if (_stopwatch.Elapsed.TotalSeconds > _timeOfLastAlarm)
{
_timeOfLastAlarm = _stopwatch.Elapsed.Seconds;
RaiseAlarm();
}
}
}
Два вопроса здесь; прежде всего, как мне передать событие в основной поток, чтобы предупредить заинтересованные стороны о событии Alarm.
Во-вторых, что касается метода Pause (), который будет вызываться объектом, работающим в основном потоке; Могу ли я напрямую манипулировать секундомером, который был создан в фоновом потоке, вызывая _stopwatch.start () / _ stopwatch.stop (). Если нет, может ли основной поток настроить логическое значение _paused, как показано выше, чтобы фоновый поток мог видеть новое значение _paused и использовать его?
Клянусь, я провел свое исследование, но эти (фундаментальные и критические) детали еще не дали мне ясности.
Отказ от ответственности: я знаю, что есть доступные классы, которые обеспечат точную конкретную функциональность, которую я описываю в своем классе Timer. (На самом деле, я считаю, что класс называется именно так, Threading.Timer). Однако мой вопрос не является попыткой помочь мне реализовать сам класс Timer, а скорее понять, как выполнять концепции, управляющие им.