Piszę bibliotekę, która zawiera funkcję planowania (nie standardową TaskScheduler
, IScheduler
...) opartą na .Net Tasks. Używam TaskCompletionSource
, a Task.Status
ma kluczowe znaczenie dla reprezentowania statusu operacji podstawowych, w tym , w tymTaskStatus.Created
, tj. Utworzono, ale jeszcze się nie rozpoczęto. Wiem, że zwrócone zadania powinny normalnie być gorące, ale dla moich ręcznie sterowanych zadań proxy, naprawdę chcę ich początkowo jako Created
.Utwórz lodowaty TaskCompletionSource?
Niestety dla mnie początkowy status TaskCompletionSource.Task
to WaitingForActivation
, czyli już minął Created
. Mówiąc inaczej, TaskCompletionSource
obsługuje dwa stany, ale muszę trzy stany:
Pytanie: Jak mogę dostać Task
że mogę ręcznie ustawić trzech różnych państw? To znaczy. Task.Status
może być ustawiony do:
1) Created
2) Jedną WaitingForActivation
/WaitingForChildrenToComplete
/WaitingToRun
/Running
3) albo z RanToCompletion
/Canceled
/Faulted
Kod poniżej zrozumiałe, skarży się na niezgodność typów . Zamiast tego mogę zamienić zadanie, zmieniając new Task<TResult>
na new Task<Task<TResult>>
, ale aby wrócić do Task<TResult>
muszę je ustawić na Unwrap()
, a niezapakowane zadanie będzie miało status WaitingForActivation
, przywracając mnie z powrotem do kwadratu.
Będę miał ich dużą liczbę, więc zablokowanie wątku z Wait()
dla każdego nie jest opcją.
Rozważałam dziedziczenie z Task
i nadrzędne członków (stosując nowy), ale jeśli to możliwe, że byłoby miło, aby dać użytkownikowi Biblioteka rzeczywiste Task
zamiast DerivedTask
, zwłaszcza odkąd przedstawiania okresowych zadań należy również oczekiwane w wielu inne miejsca.
Pomysły?
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());
}
Błędy:
* Nie można przekonwertować wyrażenia lambda delegować typu „System.Func”, ponieważ niektóre rodzaje zwrotu w bloku nie są niejawnie zamienny do zwracanego typu delegat
* Nie można niejawnie przekonwertować typu ' System.Threading.Tasks.Task 'to' TResult '
Myślę, że odpowiedziałem na ściśle powiązane pytanie [tutaj] (http://stackoverflow.com/a/22705236/1768303). – Noseratio
Myślę, że jeśli chcesz mieć większą kontrolę, nie powinieneś oprzeć swojego API na 'Zadanie ', ale na niestandardowej klasie, która eksponuje dokładnie te informacje, które chcesz eksponować. Możesz również wystawić "zadanie", ale informacja o statusie pochodzi od twojej klasy. – usr
@Noseratio: "Zadanie" w połączonym kodzie przechodzi tylko przez 2 stany: "Utworzone" i "Ukończone", podobnie do "TaskCompletionSource.Task" przechodzące tylko przez 2 stany ('WaitingForActivation' i" Completed "). Potrzebuję ** 3 ** stany ('Created',' Running', "Completed"), a mój przykładowy kod powyżej próbuje użyć async-await, aby to osiągnąć, ale jak wyjaśniono nie działa z powodu niedopasowania typu. Nie widzę sposobu modyfikowania połączonego kodu w celu obsługi stanów ** 3 ** - jakichkolwiek pomysłów? –