2015-10-05 81 views
2

讓我們看看下面的代碼:異步函數結束得太早

class C 
{ 
    static void Main(string[] args) 
    { 
     Task t = new Task(DoSthAsync); 
     t.Start(); 
     t.Wait(); 
     Console.WriteLine("Finished?"); 
    } 

    static async void DoSthAsync() 
    { 
     using (StreamReader reader = new StreamReader("file.txt")) 
     { 
      int i = 1; 
      while (!reader.EndOfStream) 
      { 
       Console.WriteLine("{0}: {1}", i++, await reader.ReadLineAsync()); 
      } 
     } 
    } 
} 

我變得很困惑。不應該這個代碼同步工作,因爲我直接等待異步方法?從一個1000行文件中,我只能打印76行。這是爲什麼?

+0

@ LasseV.Karlsen謝謝 – greenshade

回答

10

您正在使用async void其中you should never do unless you are working with events。首先,您需要讓函數返回Task而不是void,然後您必須使用Task.Run而不是new Task,以便它可以爲您處理異步函數。

static void Main(string[] args) 
{ 
    Task t = Task.Run(() => DoSthAsync()); // "Task.Run((Func<Task>)DoSthAsync)" would also work. 
    t.Wait(); 
    Console.WriteLine("Finished?"); 
} 

static async Task DoSthAsync() 
{ 
    using (StreamReader reader = new StreamReader("file.txt")) 
    { 
     int i = 1; 
     while (!reader.EndOfStream) 
     { 
      Console.WriteLine("{0}: {1}", i++, await reader.ReadLineAsync()); 
     } 
    } 
} 

你的老辦法無法知道的是,內任務完成後,t.Wait()只等到的reader.ReadLineAsync()的第一個非同步完成,現在返回Task你的外部函數的方式,當檢測到的方式內在功能已經完全完成,不僅僅是等待它的第一次延續。

+0

'DoSthAsync'仍然未返回'Task';編譯器會不高興。 –

+0

@MetroSmurf你爲什麼認爲它不會在這裏返回任務? –

+1

@MetroSmurf不,它應該是完全的快樂,你不需要'async Task'函數中的'return'語句,你只需要一個'async Task '函數,然後你只返回'T'而不是'任務'。 –

-1

當任務產生新線程時,您需要保持主線程,但它的工作原理,但是即使任務完成之前您的主線程仍然存在。

您必須確保主線程在工作線程完成前退出。

願你可以使用互斥