我正在编写一个消耗资源的库,无论出于何种原因,API 的设计方式都是在不同的线程上引发事件,但 API 的调用必须在主线程上完成。
假设我尝试使用的 API 定义为(我将省略事件定义):
public sealed class DodgyService
{
public void MethodThatHasToBeCalledOnTheMainThread() { ... }
}
为了使用这个 API,我在我的库中添加了一个名为 Service 的服务(是的,非常原始的名称),它将创建一个新任务(当我指定一个从SynchronizationContext
.
这是我的实现:
public class Service
{
private readonly TaskFactory _taskFactory;
private readonly TaskScheduler _mainThreadScheduler;
public Service(TaskFactory taskFactory, TaskScheduler mainThreadScheduler)
{
_taskFactory = taskFactory;
_mainThreadScheduler = mainThreadScheduler;
}
// Assume this method can be called from any thread.
// In this sample is called by the main thread but most of the time
// the caller will be running on a background thread.
public Task ExecuteAsync(string taskName)
{
return _taskFactory.StartNew(
() => ReallyLongCallThatForWhateverStupidReasonHasToBeCalledOnMainThread(taskName),
new CancellationToken(false), TaskCreationOptions.None, _mainThreadScheduler)
.ContinueWith(task => Trace.TraceInformation("ExecuteAsync has completed on \"{0}\"...", taskName));
}
private void ReallyLongCallThatForWhateverStupidReasonHasToBeCalledOnMainThread(string taskName)
{
Trace.TraceInformation("Starting \"{0}\" really long call...", taskName);
new DodgyService().MethodThatHasToBeCalledOnTheMainThread();
Trace.TraceInformation("Finished \"{0}\" really long call...", taskName);
}
}
现在,如果我执行我的服务调用(在主线程上)并尝试在主线程上等待应用程序进入死锁,因为主线程将等待已安排在主线程上执行的任务。
如何在不阻塞整个进程的情况下将这些调用编组到主线程上?
在某些时候,我想在创建新任务之前执行主线程的检测,但我不想破解这个。
对于任何感兴趣的人,我在这里得到了一个要点,其中包含代码和一个展示该问题的 WPF 应用程序。
顺便说一句,该库必须在 .net framework 4.0 上编写
编辑!我按照此处提供的Scott Chamberlain提供的建议解决了我的问题