Страницы

Поиск по вопросам

суббота, 27 октября 2018 г.

Синхронизация потоков с главным потоком приложения

Есть модель приложения:
объекты-задачи, которые выполняются в бесконечном цикле, информируя об результатах своей работы - пока их не информировали об прекращении работы; элемент пользовательского интерфейса (ЕПИ), который отображает информацию о результатах работы объектов-задач;
Вот код объекта-задачи:
public class DataItem { public int Index { get; set; }
public string Value { get; set; }
public object locker { get; set; } }
public class Task { private DataItem dataItem { get; set; } public EventWaitHandle local { get; set; } public EventWaitHandle exit { get; set; } Action refreshAction { get; set; }
public Task (DataItem dataItem, Action refreshAction, EventWaitHandle localEvent, EventWaitHandle exitEvent) { this.dataItem = dataItem; exit = exitEvent; local = localEvent; this.refreshAction = refreshAction; }
public void Procees () { local.WaitOne(); Random n = new Random(); while (!exit.WaitOne(0, false)) { lock (dataItem.locker) { string s = 0.ToString("D10").Remove(dataItem.Index, 1).Insert(dataItem.Index, "x"); dataItem.Index = dataItem.Index == 9 ? 0 : dataItem.Index + 1; dataItem.Value = s; } refreshAction(); Thread.Sleep(n.Next(5, 25) * 100); } local.Set(); } }
И вот код "наблюдающего" обьекта:
class Main { public EventWaitHandle main = new ManualResetEvent(false);
private void create () { main.Reset(); foreach (DataItem item in data) { item.locker = ((ICollection)data).SyncRoot; EventWaitHandle local = new AutoResetEvent(false); EventArray.Add(local); new Thread(new Task(item, RefreshGrid, local, main).Procees).Start(); local.Set(); } foreach (AutoResetEvent are in EventArray) { are.Set(); } }
private void stop () { main.Set(); bool l = true; while (l) { AutoResetEvent[] events = EventArray.Cast().ToArray(); l = WaitHandle.WaitAll(events); } } }
Объект-задача, помимо сообщения о закрытии работы, сообщает о том, что он остановил работу, что приложению необходимо для нормального закрытия. И вот в чем загвоздка - несмотря на то, что объект-задача получает сообщение о закрытии работы и сообщает об остановке, то главное окно не реагирует на сообщения от задач, это я делаю через
l = WaitHandle.WaitAll(events);
Почему не реагирует? Может, такой подход неправильный? Что порекомендуете?


Ответ

Когда вы делаете WaitAll - вы блокируете вызывающий поток (в котором GUI). Поэтому окно ни на что не реагирует. Уберите отслеживание состояния и ожидания в фоновый поток, а в GUI только отображайте состояние и передавайте команды.

Комментариев нет:

Отправить комментарий