假设我创建了一个包含此类方法的库:
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
它旨在运行一小部分代码(工作项)。
如何将上下文/调度程序替换为返回的任务中的线程池await x.ConfigureAwait(false)
以继续在线程池上,而不是在线程池上workerThread
?
我找到的当前解决方案是
Task MyLibraryMethodAsync()
{
// ...
return taskCompletionSource.Task
.ContinueWith(x => x.Result, TaskScheduler.Default);
}
但是,我不喜欢它,因为它会产生开销。可能存在更优雅的解决方案吗?