2016-10-17 4 views
2

Ich stieß versehentlich auf ein Problem, das ich lösen konnte. Ich bin jedoch besorgt darüber, dass ich nicht verstehen konnte, warum der Code mit dem Fehlercode kompiliert werden konnte (auf den ersten Platz).Parametrisierte Aktion

Es folgt der Fehler-ed-Code, die fein kompiliert:

Task<string> myTask = Task<string>.Factory.StartNew(() => 
      { 
       System.Threading.Thread.Sleep(1000); 
       return "mystrineg"; 
      }); 
      myTask.ContinueWith(t => action, CancellationToken.None, 
       TaskContinuationOptions.NotOnFaulted, TaskScheduler.Default); 

Das Problem mit dem obigen Code ist: action wird überhaupt nicht aufgerufen. Hier ist das Update ich gemacht:

Task<string> myTask = Task<string>.Factory.StartNew(() => 
      { 
       System.Threading.Thread.Sleep(1000); 
       return "mystrineg"; 
      }); 
      myTask.ContinueWith(t => action(t.Result), CancellationToken.None, 
       TaskContinuationOptions.NotOnFaulted, TaskScheduler.Default); 

Meine Frage ist, warum ist der Compiler eine parametrisierte Aktion ohne Argument aufrufen erlaubt?

+0

Alle Antworten richtig sind. Allerdings musste ich mich für diejenige entscheiden, die früh ankam und klar war. Danke euch allen! – James

Antwort

2

Meine Frage ist, warum ist der Compiler erlaubt, eine parametrisierte Aktion ohne ein Argument aufzurufen?

Es tut es nicht. In Ihrer ersten Version haben Sie action überhaupt nicht aufgerufen. Nicht einmal ohne Argumente. Sie hätten es direkt ohne das Lambda übergeben müssen oder es mit einem leeren Paar () aufrufen müssen, um es tatsächlich aufzurufen.

Während action; keine gültige Erklärung wäre, .ContinueWith wird eine Action<Task>, nicht nur nehmen, sondern auch eine Func<Task, T> und das ist genau das, was Sie vergangen ... eine Funktion einer Aufgabe nehmen, was auch immer Ihre action hat Typ Rückkehr: t => action;

2
t => action 

ist eine Abkürzung für:

t => { return action; } 

daher das Ergebnis.

3

Ihr erster Code verwendet diese overload, und was es tun wird, ist die Aktion Delegat zurückgeben und wird es überhaupt nicht ausführen.

Die Überladung, die Sie tatsächlich benötigen, ist this und Ihr zweiter Code verwendet es tatsächlich und wird Ihre Aktion ausführen.

Ich frage mich, warum Sie nicht async and await anstelle von ContinueWith und Task.Run anstelle von Task.Factory.StartNew verwendet haben, die dangerous sein können.

Ihr Code kann viel einfacher sein:

Task<string> myTask = Task.Run(() => 
         { 
          System.Threading.Thread.Sleep(1000); 
          return "mystrineg"; 
         }); 
string str = await myTask; 
action(str); 
+0

Sehr gültiger Punkt. Der Code ist jedoch alt und es gibt keine Möglichkeit, .Net 4.5 zu verwenden. – James