我正在编写一个库,其中包含基于 .Net Tasks 的调度功能(不是标准的TaskScheduler
、IScheduler
...)。我正在使用TaskCompletionSource
,并且Task.Status
对于表示底层操作的状态至关重要,包括TaskStatus.Created
,即已创建但尚未启动。我知道返回的Tasks通常应该是即时的(hot),但对于我手动控制的代理Tasks,我确实希望它们最初为Created
。
对我来说不幸的是,TaskCompletionSource.Task
的初始状态是WaitingForActivation
,即它已经过了Created
状态。换句话说,TaskCompletionSource
支持两个状态,但我需要三个状态:
问题:如何获取一个Task
,我可以手动设置为三种不同的状态?也就是说,Task.Status
可以设置为:
1) Created
2) 一个WaitingForActivation
/WaitingForChildrenToComplete
/WaitingToRun
/Running
3) RanToCompletion
/Canceled
/Faulted
中的任何一个状态。
下面的代码可以理解为类型不匹配。我可以通过将new Task<TResult>
更改为new Task<Task<TResult>>
来包装Task,但是要回到Task<TResult>
,我必须将其Unwrap()
,而取消包装的任务将具有WaitingForActivation
的状态,将我带回了起点。
我将有大量这些,所以对于每个任务使用Wait()
阻塞线程不是一个选项。
我考虑过从Task
继承并覆盖成员(使用新成员),但如果可能的话,给库用户一个实际的Task
而不是DerivedTask
会很好,特别是因为我在许多其他位置也呈现常规Tasks进行等待。
你有什么建议吗?
private TaskCompletionSource<TResult> tcs;
private async Task<TResult> CreateStartCompleteAsync()
{
await tcs.Task;
if (tcs.Task.IsCanceled)
{
throw new OperationCanceledException("");
}
else if // etc.
}
public ColdTaskCompletionSource()
{
tcs = new TaskCompletionSource<TResult>();
Task = new Task<TResult>(() => CreateStartCompleteAsync());
}
错误:
* 由于块中的一些返回类型不能隐式转换为委托返回类型,因此无法将lambda表达式转换为委托类型 'System.Func'
* 无法将类型'System.Threading.Tasks.Task'隐式转换为'TResult'
TaskStatus
将显著减少复杂性和潜在的混淆。 - Kristian Wedbergclass ScheduledTask { MyStatusEnum Status; Task Completed; }
。你甚至可以将此类型设置为可等待,尽管我认为这是一种反模式。无论如何,你的问题是合理的,应该按照所问进行回答。 - usr