2012-03-14 20 views
7

mam to metoda, która Rozpoczyna zadanie i zwraca ostatnią cahined zadanie, aby uzyskać wynik:Jak mogę uruchomić instancję kontynuacji zadania?

public Task<double> GetTask() 
{ 
    return Task.Factory.StartNew((() => 10)) 
     .ContinueWith(i => 
     { 
      return i.Result + 2; 
     }) 
     .ContinueWith(i => 
     { 
      return (double)i.Result; 
     }); 
} 

chciałbym mieć tę samą metodę zwracania samo zadanie, ale bez automatycznego uruchamiania go z Task.Factory .StartNew tak:

public Task<double> GetTask2() 
{ 
    return new Task<int>((() => 10)) 
     .ContinueWith(i => 
     { 
      return i.Result + 2; 
     }) 
     .ContinueWith(i => 
     { 
      return (double)i.Result; 
     }); 
} 

każdym razie nie udało mi się znaleźć sposób, aby rozpocząć zadanie zwrócony przez GetTask2 i uzyskać wynik. Jak mogę go uruchomić i uzyskać wynik?

Odpowiedz

1

Możesz zrobić coś takiego. Jako przykład stworzyłem trzy TextBox s dla celów ilustracyjnych.

Najpierw wybierz żądane zadanie stosując metodę jak

public Task<double> GetTask() 
{ 
    // Return choice of task. 
    return new Task<double>(() => 10.0); 
} 

Następnie zbudować kontynuację dla tego wybranego Task użyciu metody takie jak (ommitting obsługę błędów)

public Task<double> DefineTaskContinuation(Task<double> _task) 
{ 
    _task.ContinueWith(i => 
     { 
      textBox2.Text = (i.Result + 2).ToString(); 
      return i.Result + 2; 
     }, TaskScheduler.FromCurrentSynchronizationContext()) 
    .ContinueWith(i => 
     { 
      textBox3.Text = (i.Result + 2).ToString(); 
     }, TaskScheduler.FromCurrentSynchronizationContext()); 
    return _task; 
} 

if masz formę z textBox1, textBox2 i textBox3, można wypełnić te pola tekstowe, wykorzystując dane wyjściowe z countinuation w następujący sposób:

private void button1_Click(object sender, EventArgs e) 
{ 
    Task<double> task = DefineTaskContinuation(GetTask()); 
    task.Start(); 
    textBox1.Text = task.Result.ToString(); 
} 

wyjściowa:

The Results

Mam nadzieję, że to pomaga.

Edytuj: Ze względu na bardzo poprawne komentarze @usr, odpowiedź została zmieniona. Zauważ, że TaskScheduler.FromCurrentSynchronizationContext() nie jest wymogiem, ale służy do ułatwienia drukowania wydruków do wątku interfejsu użytkownika. Wszystkiego najlepszego.

+1

To nie zadziała. Musisz zacząć oryginalne, pierwsze zadanie. Nie ostatni z łańcucha. – usr

+0

Dlaczego? To nie jest pytanie. Po prostu wykonaj instancję zadania z metody. Następnie uruchom go. Prosty. – MoonKnight

+1

Wywołujesz start w zadaniu kontynuacji. Nie możesz rozpocząć zadania kontynuacji. Uruchomi się automatycznie, gdy jego poprzednik zostanie zakończony. Nie możesz zmusić go do rozpoczęcia. – usr

2

coś takiego:

public Task<double> GetTask() 
{ 
    var rootTask = new Task<int>((() => 10)); 
    var continuationTask = rootTask 
     .ContinueWith(i => 
     { 
      return i.Result + 2; 
     }) 
     .ContinueWith(i => 
     { 
      return (double)i.Result; 
     }); 
    rootTask.Start(), 
    return continuationTask; 
} 

Jeśli chcesz uruchomić zadanie dopiero później można wrócić zarówno ze swojej funkcji.

+0

To jest możliwe rozwiązanie, ale nie jest to odpowiedź na moje pytanie.Mimo wszystko dziekuję. – gigi

+0

Czego mi brakowało w związku z twoim pytaniem? Dlaczego jest to możliwe, ale nie jest to odpowiedź? – usr

+0

Chodzi o to, że nie chcę zwracać krotki, ale zadanie zwraca wynik końcowy i można go sartować, na przykład: task.Root(). Start(). Jeśli czytasz tytuł pytania, jest on wyraźny. – gigi

0
[TestFixture] 
public class TaskTester 
{ 
    [Test] 
    public void Test() 
    { 
     Tuple<Task<int>, Task<double>> result = GetResult(); 
     result.Item1.Start(); 
     Assert.That(result.Item2.Result, Is.EqualTo(12)); 
    } 

    private static Tuple<Task<int>, Task<double>> GetResult() 
    { 
     var task1 = new Task<int>(() => 10); 
     Task<int> task2 = task1.ContinueWith(i => i.Result + 2); 
     Task<double> task3 = task2.ContinueWith(i => (double)i.Result); 
     return new Tuple<Task<int>, Task<double>>(task1, task3); 
    } 
} 
2

Można utworzyć kolejną Task, który rozpoczyna rodzica Task, następnie ustawia się na kontynuację i zwraca wynik kontynuacji. Chociaż ma tę wadę, że blokuje jeden wątek podczas oczekiwania na ten, który faktycznie wykonuje te kontynuacje.

public static Task<double> GetTask() 
{ 
    return new Task<double>(
     () => Task.Factory.StartNew(() => 10) 
        .ContinueWith(
         i => 
         { 
          return i.Result + 2; 
         }) 
        .ContinueWith(
         i => 
         { 
          return (double)i.Result; 
         }).Result); 
} 
Powiązane problemy