2017-04-26 2 views
1

Ich habe gelesen über das Erstellen einer Fortsetzung für mehrere Vorgänger in MSDN https://msdn.microsoft.com/en-us/library/ee372288(v=vs.110).aspx und habe eine harte Zeit, den Code zu verstehen, eines ihrer Beispiele verwendet. Ich füge den folgenden Code ein.TaskFactory.StartNew <TResult> Methode (Func <Objekt, TResult>, Objekt)

for (int ctr = 1; ctr <= 10; ctr++) { 
    int baseValue = ctr; 
    tasks.Add(Task.Factory.StartNew((b) => 
     { 
     int i = (int) b; 
     return i * i; 
     }, 
     baseValue)); 
} 

Wenn ich über StartNew Überlastung zu lesen, die MSDN states:

public Task<TResult> StartNew<TResult>(
    Func<object, TResult> function, 
    object state 
) 

Parameter

Funktion

Typ: System.Func<Object, TResult>
Ein Funktionsdelegat, der das zukünftige Ergebnis zurückgibt, um über die Task<TResult> verfügbar zu sein.

Zustand

Typ: System.Object
Ein Objektdaten enthält, durch die Funktion delegieren verwendet werden.

Um genau zu sein, in ihrem Beispiel verstehe ich nicht die Verwendung von baseValue, wenn b als Object an die Funktion übergeben wird.

+0

'baseValue' ist ein Zustandsobjekt, das an den Delegaten übergeben wird, der für' StartNew' bereitgestellt wird. Im Beispiel nimmt 'baseValue' den Wert von' ctr' an, während die Schleife ausgeführt wird. [Auf einem anderen Hinweis bleiben Sie weg von 'StartNew'] (https://blog.stephencleary.com/2013/08/startnew-is-dangerous.html) – JSteward

+0

Wofür ist b? –

+0

b ist der Parameter, der an die lamda übergeben wird, es entspricht in etwa "void SomeFunc (int b)". – JSteward

Antwort

2

Was ist Func<object, TResult>? Es handelt sich um einen Delegattyp, der akzeptiert und TResult: TResult MethodName(object b) zurückgibt.

Hier in Codebeispiel das Verfahren mit Inline-Lambda gebaut wird, die object b akzeptiert und gibt int (die Liste der Aufgaben sehen, die int zurückkehren - List<Task<int>> tasks):

private int Square(object b) 
{ 
    int i = (int) b; 
    return i * i; 
} 

Jetzt müssen Sie rufen Sie diese Methode auf, also übergeben Sie den zweiten Parameter baseValue. Also für jede Nummer von 1 bis 10 bekommen Sie das Quadrat davon: 1 + 4 + 9 + 16 + 25 + 36 + 49 + 64 + 81 + 100, und danach summieren Sie sie und erhalten 385.

werden
for (int ctr = 1; ctr <= 10; ctr++) 
{ 
    resultList.Add(Square(ctr)); 
} 

sondern ganze Berechnungen innerhalb der Aufgabe auftreten:

So kann ganzer Code als gelesen werden.
Dies kann wie folgt umgeschrieben werden:

for (int ctr = 1; ctr <= 10; ctr++) 
{ 
    // get a local copy of ctr 
    var baseValue = ctr; 
    // create a task which will get the square 
    tasks.Add(Task.Run(() => baseValue * baseValue)); 
    // or with a method introduction 
    tasks.Add(Task.Run(() => Square(baseValue))); 
} 

aber in diesem Fall werden Sie einen Verschluss erhalten, so dass die Delegierten innerhalb Task werden jedes Mal zu vergleichen mit einer anfänglichen Variante ohne Verschlüsse (Danke für @CoryNelson neu erstellt werden).

Beachten Sie, dass Anfangscode eine Probe ist, und nicht als Muster verwendet werden soll, in der Produktion Code zu reproduzieren: Es blockiert die aktuelle Ausführung mit .Result (was in Ordnung ist nur als main Methode nicht async sein könnte) und nutzt StartNew, welche can behave unexpectedly.

einige nützliche Links:

+1

Ich würde hinzufügen, dass der Grund, warum Sie diese Überladung im Vergleich zu einem Capturing Lambda verwenden, ist, dass das Capturing jedes Mal einen neuen Delegaten zuweist, während ein nicht erfassendes nur einmal zugewiesen wird. –

+0

@CoryNelson Danke, fügte das hinzu. – VMAtm

+0

Scheint wie Lambda Konzept ist nicht klar in meinem Kopf. Ich hatte gehofft zu sehen, 'für (int ctr = 1; ctr <= 10; ctr ++) { objekt b = objekt (ctr); tasks.Add (Task.Factory.StartNew ((b) => { int i = (int) b; return i * i; }); } ' –

Verwandte Themen