Страницы

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

понедельник, 16 декабря 2019 г.

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

#c_sharp #net #многопоточность


Есть модель приложения:


объекты-задачи, которые выполняются в бесконечном цикле, информируя об результатах
своей работы - пока их не информировали об прекращении работы;
элемент пользовательского интерфейса (ЕПИ), который отображает информацию о результатах
работы объектов-задач;


Вот код объекта-задачи:

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);


Почему не реагирует? Может, такой подход неправильный? Что порекомендуете?
    


Ответы

Ответ 1



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

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

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