Управляемый событиями конечный автомат C # должен выпустить сборщик событий, используя Windows.Forms.Timer - PullRequest
0 голосов
/ 20 июля 2011

В нашем унаследованном коде VB6 мы использовали системный таймер для выполнения обратного вызова, чтобы конечные автоматы могли работать без блокировки обработчиков событий.Пример кода Psuedo

Sub Unhooked(State info)
    Select Case info
        Case 1
            NextState = somestate1
        Case 2
            NextState = somestate2
        Case 3
            NextState = somestate3
    End Select
    RunStateMachine
End Sub

Sub RunStateMachine()
    MyObject.GoDoSomethingAndCallMeBack
End Sub

Sub MyObject_EventCallback(State info)
    APITimer.SetUpCallBackTarget (Unhooked, info)
    APITimer.CallMeBackInASec
End Sub

Надеемся, вы поймете, что в конечном автомате выполняется какой-то вызов, который в дальнейшем будет вызывать срабатывание обработчика событий, и он устанавливает таймер для выполнения обратного вызова, чтобыкод обработчика событий может завершиться, прежде чем мы перейдем к следующему состоянию.

Я продолжаю в том же духе в C #, но это неправильно, так как я уверен, что язык предоставит более приятный способ сделать это.Поскольку мой конечный автомат C # все еще вызывает объекты VB6, которые вызывают события в потоке пользовательского интерфейса, есть ли лучший способ «отцепить» обработчик событий, чтобы он был освобожден до того, как конечный автомат продолжит работу?

Я думал, что мог бы использовать BeginInvoke, чтобы добавить сообщение в насос для запуска конечного автомата, но в том же потоке вместо потока пула потоков, но мой класс не является формой или элементом управления.Я думаю, что мог бы придумать решение, которое не использует таймеры, но, ну, они очень просты в использовании, поэтому любые идеи будут великолепны.

1 Ответ

1 голос
/ 20 июля 2011

Чтобы решить вашу непосредственную проблему, вы можете поставить в очередь Task в контексте потока пользовательского интерфейса, например:

var ui = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.StartNew(() => Unhooked(info), CancellationToken.None,
    TaskCreationOptions.None, ui);

Пользовательский интерфейс SynchronizationContext может быть обнаружен, даже если ваш объект не является формой иликонтроль.Для получения дополнительной информации о SynchronizationContext см. мою статью MSDN .

Если у вас это много в коде, вы, вероятно, захотите заключить его в вспомогательный метод:

public void CallbackLater(Action action)
{
  Task.Factory.StartNew(action, CancellationToken.None,
    TaskCreationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
}

void MyObject_EventCallback(State info)
{
  CallbackLater(() => Unhooked(info));
}

В более широком смысле серьезно рассмотрите Async CTP и разработку API-интерфейса асинхронного шаблона на основе задач вместо того, чтобы вызывать события в пользовательском интерфейсе.поток (т. е. асинхронный шаблон на основе событий).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...