假设我创建了一个包含这样的方法库:如何将同步上下文/任务调度程序替换为TaskCompletionSource.Task中的另一个ConfigureAwait(false)?
Task MyLibraryMethodAsync()
{
var taskCompletionSource = new TaskCompletionSource<object>();
Action myWorkItem =
() =>
{
// Simulate some work.
// Actual work items depend on input params.
Thread.Sleep(TimeSpan.FromSeconds(1));
taskCompletionSource.SetResult(null);
};
// The next two lines is simplification for demonstration.
// I do not have access to the workerThread - it is created
// and managed for me by another lib.
// All I can do - is to post some short work items to it.
var workerThread = new Thread(new ThreadStart(myWorkItem));
workerThread.Start();
return taskCompletionSource.Task;
}
我的lib中的任何用户都可以拨打MyLibraryMethodAsync
这样
await MyLibraryMethodAsync().ConfigureAwait(false);
VeryLongRunningMethod();
void VeryLongRunningMethod()
{
Thread.Sleep(TimeSpan.FromHours(1));
}
在这里,问题就来了 - VeryLongRunningMethod
将内被执行taskCompletionSource.SetResult(null)
调用,因此它会阻止workerThread
很长一段时间,这是不希望的行为,因为workerThread
是为了运行小porti代码(工作项目)。
如何替代上下文/调度到线程池返回的任务,因此await x.ConfigureAwait(false)
继续对线程池内,但不是在workerThread
?
目前的解决方案,我发现是
Task MyLibraryMethodAsync()
{
// ...
return taskCompletionSource.Task
.ContinueWith(x => x.Result, TaskScheduler.Default);
}
不过,我不喜欢它由于开销它创建。 可能更优雅的解决方案存在?
从用户的角度来看,你是对的。但我是lib开发人员,我需要确保lib用户不会阻止工作线程。 –
请参阅编辑 - 使用Task.Run(()=> taskCompletionSource.SetResult(null));设置结果? – Matthias
这给出了与我目前的解决方案相同的开销。无论如何,塞维解决了我的问题。 –