2015-01-13 22 views
7

Nie jestem pewien, czy jest to możliwe, więc o mnie:Podjęcie zadania jako parametr

mam sekwencję działań, aby wykonać wiele

async Task MethodA(...) 
{ 
    // some code 
    // a call to specific Async IO bound method 
    // some code 
} 

istnieją również MethodB(), MethodC(), etc , a wszystkie mają dokładnie ten sam kod, z wyjątkiem wywołania określonej metody Async IO bound. Próbuję znaleźć sposób przekazania wskaźnika zadania do metody, abyśmy mogli wykonać go później w Method().

kim jestem obecnie robi to:

private async Task Method(Func<Task<Entity>> func) 
{ 
    // some code 
    var a = await task.Run(func); 
    // some code 
} 

var task = async() => await CallToIOBoundTask(params); 
Method(task); 

Kod ten jednak ciągnie nowego wątku za każdym razem, co nie jest wymagane dla IO związany zadania i należy ich unikać.

Czy istnieje sposób na refaktoryzację kodu, aby nie używać nici ThreadPool? Celem jest posiadanie kodu takiego:

private async Task Method(Task<Entity> task) 
{ 
    // some code 
    var a = await task; 
    // some code 
} 

Należy również wspomnieć, że różne wywołania IO mają różne sygnatury metod. Ponadto zadanie można uruchomić tylko w treści Method(), a nie wcześniej.

+0

Czy chcesz poczekać, aż rozpocznie się instrukcja w metodzie 'Method()' dla zadania asynchronicznego? Jeśli tak, to Twój przykładowy kod w pytaniu jest niepoprawny (oczekujesz zadania _istniejącego zamiast tworzenia), a odpowiedź już dostarczona jest tym, czego potrzebujesz. Ale jeśli chcesz tylko móc poczekać na uruchomione zadanie przed wywołaniem metody 'Method()', zwróć uwagę, że możesz to łatwo zrobić: po prostu zadzwoń np. przekazać wartość zwracaną wywołania do 'CallToIOBoundTask()' jako argument dla twojego wywołania metody 'Method()'. –

+0

@PeterDuniho Odpowiedź na twoje pytanie jest w ostatnim zdaniu pytania - zadanie musi rozpocząć jego wykonanie w metodzie(). – Goran

Odpowiedz

16

Oczywiście, wystarczy wywołać func, wracaj zadania i await go:

async Task Method(Func<Task<Entity>> func) 
{ 
    // some code 
    var a = await func(); 
    // some code 
} 

Również podczas wysyłania tego wyrażenia lambda, ponieważ wszystko to robi to wywołanie metody, która w async sam zwraca zadanie, to nie musi być async w sobie:

Method(() => CallToIOBoundTask(params)); 

że jest w porządku tak długo, jak wszystkie te rozmowy powrócić Task<Entity>. Jeśli nie, możesz użyć tylko Task (co oznacza rozpoczęcie operacji i oczekiwanie na jej zakończenie) i nie będzie można użyć wyniku.

+0

Heh, próbowałem bez nawiasów i to nie działało. :) AS dla drugiej sugestii, co wygeneruje IL dla tej części:() => CallToIOBoundTask (params)? Czy to będzie asynchroniczna metoda zadania, czy nie? Nie mogę wygenerować tego kodu jako nieważnego. – Goran

+0

@Goran Nie będzie to metoda "asynchroniczna". Ale zwróci zadanie, ponieważ 'CallToIOBoundTask' zwraca zadanie. Ponadto nie można go unieważnić, ponieważ parametr ten nie jest "Akcja", ale "Func >". Jeśli chcesz się upewnić, że możesz rozszerzyć tę wartość lambda na '() => {return callToIOBoundTask (params); } 'który jest dokładnie taki sam. – i3arnon