2012-07-31 64 views
2

我一直在試圖讓我的頭最近圍繞C#的新的異步/等待和Task.Run功能。在這樣做的時候,我寫了一些簡單的測試代碼寫入控制檯,以便我可以看到事件發生的順序,在這裏和那裏引入Thread.Sleep以確保事情按照我預期的順序發生。Thread.Sleep在Task.Run

這裏是我的測試一個

[Test] 
public void TaskRun() 
{ 
    Console.WriteLine("Before"); 
    Task.Run(() => Console.WriteLine(_terminator.IWillBeBack())); 
    Console.WriteLine("After"); 
} 

具有以下終結者類:

public class Terminator 
{ 
    public string IWillBeBack() 
    { 
     return "I will be back"; 
    } 
} 

從這個我期望的結果很可能是之前後,再我會回來。這確實發生了什麼。然後,我對IWillBeBack方法進行更改,讓它睡3秒。造成這種情況的代碼:

public class Terminator 
{ 
    public string IWillBeBack() 
    { 
     Thread.Sleep(3000); 
     return "I will be back"; 
    } 
} 

我預計結果仍然是之後之前,然後加入3秒後重後我會回來。這不是發生了什麼。我反而得到之前之後,但從來沒有我會回來

這是爲什麼?

當我調試它清楚地通過代碼,睡覺和返回。我不需要在任何生產代碼中以這種方式使用Thread.Sleep,但是我想對第二種情況下爲什麼我將不會回寫寫入控制檯。

+0

我測試今天有點懶,所以我只會參考答案。我幾天前寫了一些東西,可以幫助理解TPL + async/await:http://blog.tedd.no/2012/07/28/asyncawait-http-server-in-c/ – 2012-07-31 11:56:18

回答

5

在您嘗試打印「我會回來」之前,您的測試已完成。你沒有做任何事情要等到完成。取決於測試運行器,但是測試完成後,重定向Console.WriteLine可能已經斷開連接。

如果你想看到它完成,改變你的測試:

[Test] 
public void TaskRun() 
{ 
    Console.WriteLine("Before"); 
    var task = Task.Run(() => Console.WriteLine(_terminator.IWillBeBack())); 
    Console.WriteLine("After"); 
    task.Wait(); 
} 
+0

這很有道理。我跑了你的測試,它現在按預期工作:) – Halvard 2012-07-31 11:44:46

+0

我只是「幸運」,它寫了「我會回來」在第一個案件然後(因爲我什麼也沒有做任何等待在那裏)?我很幸運,在測試完成之前,它恰好能夠及時寫入控制檯。 – Halvard 2012-07-31 11:51:54

+0

@Halvard:是的。測試拆解可能會有一些「稍微昂貴」的工作,這會讓您的其他線程處於優勢地位。 – 2012-07-31 11:53:30

1

如果你使用VS 2012的MS測試框架,你也可以這樣寫

[TestMethod] 
public async Task TaskRun() 
{ 
    Console.WriteLine("Before"); 
    Task t = Task.Run(() => Console.WriteLine(IWillBeBack())); 
    Console.WriteLine("After"); 
    await t; 
} 

private string IWillBeBack() 
{ 
    Thread.Sleep(3000); 
    return "I will be back"; 
} 
+0

我期待這個工作,當我看到你的代碼,但運行你的測試時,我得到*之前*和*之後*,但不是*我會​​回來*。據我瞭解task.Wait()和等待任務之間的區別是,第一個塊和第二個不。這可能是你的不工作的原因嗎? (順便說一句,我看到在默認測試GUI窗口的輸出VS 2012,並使用NUnit的框架。難道是我通過欺騙?) – Halvard 2012-07-31 12:31:45

+0

AFAIK,NUnit的不支持'async'單元測試。我相信現在只有MSTest和xUnit能夠做到。 – 2012-07-31 12:57:11

+1

更新:當寫了以前的評論時,NUnit不支持'async'單元測試,但現在它確實。 – Halvard 2013-08-21 06:53:30