C # Выполнение задачи в указанных блоках UIThread (не в продолжении), когда ThreadUI переходит в спящий режим - PullRequest
0 голосов
/ 10 сентября 2018

Я разрабатываю приложение, которое требует совершать звонки на разные серверы: некоторые из них являются серверами ActiveX (или COM), другие могут работать в ThreadPool. Поскольку поставщики этих серверов принадлежат разным компаниям, и некоторые из них используют (действительно) старые технологии (библиотеки C / C ++, обернутые в .Net), у них нет согласованного (если не вовсе) механизма тайм-аута.

Я начал реализовывать асинхронный вызов, используя Task и Timeout, предложенные в разных статьях (спасибо Reed Copsey Jr., Stephen Toub и Stephen Cleary).

На стороне "клиента" (для тестового приложения используется MainForm) у меня есть:

int result = await sB.TheForm.F2Async ("TEST", 1.5, комбинированный CTS);

где:

    - sB.TheForm: is the WinForm that runs in the second UIThread. The MainForm spun the "TheForm" Form in a different thread making an UIThread.
    - "TEST", 1.5: are the actual parameters 
    - combinedCTS is of CancellationTokenSource type 

На стороне сервера функция F2Async планирует функцию F2 во втором UIThread как TASK (workingTask) и быстро и асинхронно :) планирует

var completedTask = await Task.WhenAny(workingTask, Task.Delay(nTimeoutMilisec));

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

var workingTask = Task.Factory.StartNew<int>(
                  () => F2(s1, d1), 
                  combinedCTS.Token, 
                  TaskCreationOptions.DenyChildAttach, 
                  TaskSchedulerForm);

где:

    - F2() is the synchronous function (the ActiveX function)
    - TaskSchedulerForm: is initialized in the LOAD event handler of the second UIThread as
TaskSchedulerForm = TaskScheduler.FromCurrentSynchronizationContext();

Если функция F2 переходит в спящий режим (или блокирует), ПОЧЕМУ блокируется Task.Factory.StartNew?

, поскольку при вызове StartNew (функция F2Async) ожидание не ожидается, код должен продолжаться в основном потоке пользовательского интерфейса до ожидания задач WhenAny.

Я пробовал по-другому, чтобы запустить await Task.WhenAny(...). Когда F2 блокирует оператор после RunNew, он будет выполнен только после завершения F2.

F2 запускает второй (требуемый) поток пользовательского интерфейса. Если функция F2 не блокирует, то она все еще работает, когда Task.WhenAny начинает ожидать - и это хорошо, потому что теперь я могу принудительно запустить продолжение в случае тайм-аута.

...