2015-11-13 71 views
1

嗨,我有以下短代碼提取。該代碼的目的是從任務中返回一個人物並獲得結果,以便它可以在main中訪問。C#從任務返回數據

我有的代碼如下,但編譯時出現兩個錯誤。

錯誤2「System.Threading.Tasks.Task multi_threaded_tasks.Program.ExecuteAsync_GetPerson()」具有錯誤 返回類型
錯誤1的對象引用是所必需的 非靜態字段,方法,或物業 「multi_threaded_tasks.Program.ExecuteAsync_GetPerson()」

我不知道我要去哪裏錯了,你可以提供任何幫助將是有益的。 P.S如果有更好的方法來返回對象我打開建議,但我希望功能調用是分開的。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Threading; 
namespace multi_threaded_tasks 
{ 
    public class Person 
    { 
     public string first_name; 
     public string last_name; 
     //Constructor 
     public Person() 
     { 
      first_name=""; 
      last_name=""; 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      Console.WriteLine("Main started:"); 
      CancellationTokenSource cancelSource; 
      Task<Person> t_person = Task<Person>.Factory.StartNew(
       function: ExecuteAsync_GetPerson, 
       cancellationToken: cancelSource.Token, 
       creationOptions: TaskCreationOptions.PreferFairness, 
       scheduler: TaskScheduler.Default); 

      Person main_person = t_person.Result; 
      Console.WriteLine("The person first name:" + main_person.first_name); 
      Console.WriteLine("The person last name:" + main_person.last_name); 
      Console.WriteLine("Main Ended:"); 
     } 

     async Task<Person> ExecuteAsync_GetPerson() 
     { 
      Console.WriteLine("ExecuteAsync_GetPeople started:"); 
      Person a_person = new Person(); 
      a_person.first_name=""; 
      a_person.last_name=""; 
      await Task.Delay(2000); // Wait 2 seconds 
      Console.WriteLine("ExecuteAsync_GetPeople returning:"); 
      return a_person; 
     } 
    } 
} 
+1

1.你沒有初始化你的'CancellationSource',這就是你得到'NullReferenceException'的原因。 2.'StartNew'預計'Func ',而不是'Func <任務>',這是導致其他錯誤。 – MarcinJuraszek

+1

不要使用'Task.Factory.StartNew',如果你在.NET 4.5+上,除非你真的知道,你在做什麼。改爲使用'Task.Run'。 – Dennis

回答

2

Your code do反正沒什麼意義。

由於這兩種方法一個控制檯應用程序,其中之一是應用程序的入口點,你不能從異步方法的任何好處,因爲你想獲得任務結果在您的主要方法。這意味着,主線程將被阻塞,並且無法取消任何內容。

我已經從代碼中扔掉了一些垃圾並添加了另一個示例async方法。這可能是你想要的:

public class Person 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
} 

class Program 
{ 
    static async Task<Person> GetPersonAsync(CancellationToken cancellationToken) 
    { 
     Console.WriteLine("GetPersonAsync started."); 

     var person = new Person 
     { 
      FirstName = "John", 
      LastName = "Doe" 
     }; 

     await Task.Delay(5000, cancellationToken); // Wait 5 seconds 
     Console.WriteLine("GetPersonAsync ended."); 
     return person; 
    } 

    static async Task TestGetPersonAsync(CancellationToken cancellationToken) 
    { 
     Console.WriteLine("TestGetPersonAsync started."); 

     try 
     { 
      var person = await GetPersonAsync(cancellationToken); 

      Console.WriteLine("The person first name:" + person.FirstName); 
      Console.WriteLine("The person last name:" + person.LastName); 
      Console.WriteLine("TestGetPersonAsync ended."); 
     } 
     catch (OperationCanceledException) 
     { 
      Console.WriteLine("TestGetPersonAsync cancelled."); 
     } 
    } 

    static void Main(string[] args) 
    { 
     Console.WriteLine("Main started:"); 

     // let's get person asynchronously; 
     // this object will contain our cancellation token;    
     var cts = new CancellationTokenSource(); 
     // dummy variable here is needed to aviod compiler warning, 
     // since TestGetPersonAsync is async, and we will not (and cannot) await it 
     var _ = TestGetPersonAsync(cts.Token); 

     // if TestGetPersonAsync is not finished yet, we are going to cancel it; 
     // wait for a new line 
     Console.WriteLine("Press ENTER to cancel TestGetPersonAsync and to exit application."); 
     Console.ReadLine(); 
     if (!_.IsCompleted) 
     { 
      cts.Cancel(); 
     } 

     Console.WriteLine("Main ended."); 
    } 
} 
+0

這被認爲是一個採樣器代碼來理解返回使用的任務在c#對象的概念,而不使代碼複雜閱讀或理解。我知道主要是在現實中什麼都不做,其他工作負載將會運行,但爲了簡單起見,這些被省略了。感謝您的很好的解決方案,但! –

2

Task.Factory.StartNew具有以下定義:

public Task<TResult> StartNew(Func<TResult> function... 

,而你試圖傳遞

public Task<TResult> StartNew(Func<Task<TResult>> function... 

如果你想開始一個異步方法,您可以使用:

Task<Person> t_person = Task.Run(() => a()); 
Person main_person = t_person.Result;