我正在开发一个需要对不同服务器进行调用的应用程序:其中一些是ActiveX(或COM)服务器,其他可以在ThreadPool中运行。由于这些服务器的提供商来自不同的公司,并且其中一些服务器正在使用(确实)过时的技术(包装在.Net上的C / C ++ dll),因此它们没有一致的超时机制(如果没有的话)。
我开始使用Task和不同文章中建议的超时来实现异步调用(感谢Reed Copsey,Jr.,Stephen Toub和Stephen Cleary)。
在“客户端”端(对于测试应用程序是MainForm),我有:
int结果=等待sB.TheForm.F2Async(“ TEST”,1.5,CombinedCTS);
其中:
- 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函数将第二个UIThread中的F2函数作为TASK(工作任务)进行调度,并快速异步地进行:)调度
var completedTask = await Task.WhenAny(workingTask, Task.Delay(nTimeoutMilisec));
要在其他UI线程中安排任务,请使用
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)的调用,因此代码应在主线程ui中继续,直到WhileAny任务的等待。
我尝试了不同的方法来运行await Task.WhenAny(...)
。当F2阻塞时,仅在F2完成后才执行RunNew之后的语句。
F2运行第二个(所需的)UI线程。如果函数F2没有阻塞,则在Task.WhenAny开始等待时它仍在运行-很好,因为现在我可以在出现超时的情况下强制继续运行。