【发布时间】:2016-04-12 00:38:44
【问题描述】:
假设我创建了一个包含此类方法的库:
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;
}
我的库的任何用户都可以像这样调用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);
}
但是,我不喜欢它,因为它会产生开销。 可能存在更优雅的解决方案吗?
【问题讨论】:
标签: c# multithreading async-await task-parallel-library taskcompletionsource