Бесконечный цикл асинхронно

241
18 мая 2017, 08:43

Имеется необходимость на всём протяжении работы программы в некотором классе Watcher получать сообщения из некоего динамического буфера (Mailslot, для которого сделана обертка и имеется метод string Mailslot.GetMessage()). Класс Watcher создается при старте приложения, имеющего GUI, и, собственно, служит для наблюдения за содержимым Mailslot.

Разумеется, вариант с таким подходом работает:

bool DoListen = true;
while (DoListen)
    {
         var msg = Watcher.Instance().MailSlotServer.GetNextMessage();
         if (msg != null)
            {
                listBox1.Items.Insert(0, msg);
            }
         Application.DoEvents();
    }

Но такой подход не видится мне правильным. По идее, цикл опроса буфера нужно вынести в отдельный поток, или использовать BackgroundWorker, но подумалось мне, что данный момент можно было бы оформить и при помощи async/await. Но это не особо получается пока:

В классе Watcher создаю метод:

    private async Task<string> GetMessage()
    {
        return await Task.Run(() => { var s = mailSlotServer.GetNextMessage(); return s; });
    }

И там же реализую цикл:

    public async void StartListen(CancellationToken ct)
    {
        while (!ct.IsCancellationRequested)
        {
            string s = await GetMessage();
            if (!string.IsNullOrEmpty(s))
               (FormMain.ActiveForm as FormMain).listBox1.Items.Insert(0, s);
            await Task.Delay(100);
        }
    }

Теперь при старте приложения пытаюсь вызвать цикл прослушивания, для теста пока вызываю из обработчика события Load:

...
var ct = new CancellationToken();
Watcher.Instance().StartListen(ct);
...

VS вываливается с ArgumentNullException при попытке вставки строки в listBox1.

Полагаю, что на момент попытки вставки s переменная, полученная через await GetMessage() действительно пустая.

Вот и возникает вопрос, как правильнее реализовать такой механизм?

UPDATE

Всё заработало именно в указанном виде, а ошибка возникала из-за использования ActiveForm, который становится null как только форма перестает быть активной (спасибо Pavel Mayorov!)

Если отказаться от использования ActiveForm, то всё работает. listBox(или другой GUI-контрол) можно передавать внутрь метода StartListen по ссылке, или не использовать тут GUI вовсе (что и было сделано автором вопроса).

READ ALSO
Ошибка 404 при обновлении страницы SPA-приложения

Ошибка 404 при обновлении страницы SPA-приложения

Есть SPA-приложение со стэком MVC + WebAPI + Angular4Вот backend-маршруты:

375
Отображение нескольких ToolTip&#39;ов на одном окне

Отображение нескольких ToolTip'ов на одном окне

Если создать пару ToolTip'ов, привязать их к 2 разным контролам и отобразить используя IsOpen, второй ToolTip ни за что не закроется

257
C#. Thread.CurrentThread.IsBackground

C#. Thread.CurrentThread.IsBackground

Вопрос, наверняка, окажется глупым и не носящем практической ценности, но тем не менееСейчас вплотную разбираюсь с многопоточностью и параллельным...

189
Как передать звук с сервера на клиент?

Как передать звук с сервера на клиент?

Доброго времени суток

236