2012-11-03 56 views
0

我打印出AsyncDemoViewModel中的Messages屬性字符串列表。等待不釋放異步方法中的調用線程

如果我使用了Thread.Sleep(1000)中GetVideosSlowlyAsync()的輸出是

Time spent: 4001 milliseconds 

- Started on thread 18, finished on thread 18 
- Started on thread 18, finished on thread 18 
- Started on thread 18, finished on thread 18 
- Started on thread 18, finished on thread 18 

如果我使用等待Task.Delay(1000)中GetVideosSlowlyAsync()的輸出是

Time spent: 4053 milliseconds 


- Started on thread 12, finished on thread 19 
- Started on thread 19, finished on thread 16 
- Started on thread 16, finished on thread 19 
- Started on thread 19, finished on thread 9 

爲什麼await調用沒有釋放調用線程?我期待await版本的完成時間快大約4倍。

控制器代碼:

public class AsyncDemoController : Controller 
{ 
    private DepartmentDb _db; 

    public AsyncDemoController(DepartmentDb db) 
    { 
     _db = db; 
    } 

    public async Task<ActionResult> Index() 
    { 

     var sw = Stopwatch.StartNew(); 
     var v1 = await GetVideosSlowlyAsync(); 
     var v2 = await GetVideosSlowlyAsync(); 
     var v3 = await GetVideosSlowlyAsync(); 
     var v4 = await GetVideosSlowlyAsync(); 

     var vm = new AsyncDemoViewModel() {Videos = v1.Item2, Messages = new List<string>()}; 
     sw.Stop(); 
     vm.Messages.Add(string.Format("Time spent: {0} milliseconds", sw.ElapsedMilliseconds)); 
     vm.Messages.Add(v1.Item1); 
     vm.Messages.Add(v2.Item1); 
     vm.Messages.Add(v3.Item1); 
     vm.Messages.Add(v4.Item1); 

     return View(vm); 
    } 

    private async Task<Tuple<string, IEnumerable<Video>>> GetVideosSlowlyAsync() 
    { 
     var t1 = Thread.CurrentThread.ManagedThreadId; 
     await Task.Delay(1000); // Thread.Sleep(1000); 
     var t2 = Thread.CurrentThread.ManagedThreadId; 
     return Tuple.Create(string.Format("Started on thread {0}, finished on thread {1}", t1, t2), _db.Videos.AsEnumerable()); 
    } 

} 

回答

3

的await方法等待的爲GetVideosSlowlyAsync方法來完成。您需要將等候轉移到需要手術結果的地方:

public async Task<ActionResult> Index() 
{ 

    var sw = Stopwatch.StartNew(); 
    var v1 = GetVideosSlowlyAsync(); 
    var v2 = GetVideosSlowlyAsync(); 
    var v3 = GetVideosSlowlyAsync(); 
    var v4 = GetVideosSlowlyAsync(); 

    var vm = new AsyncDemoViewModel() {Videos = (await v1).Item2, Messages = new List<string>()}; 
    sw.Stop(); 
    vm.Messages.Add(string.Format("Time spent: {0} milliseconds", sw.ElapsedMilliseconds)); 
    vm.Messages.Add((await v1).Item1); 
    vm.Messages.Add((await v2).Item1); 
    vm.Messages.Add((await v3).Item1); 
    vm.Messages.Add((await v4).Item1); 

    return View(vm); 
} 
0

要調用await GetVideosSlowlyAsync()將返回給調用方法,直到任務完成。如果你想看到你期待的結果,你需要刪除這個等待。這樣它將一個接一個地開始所有4 GetVideosSlowlyAsync(),而Task.Delay()方法在線程池中休眠。

嘗試這樣的事情,

List<Task> taskList = new List<Task>(); 
taskList.Add(GetVideosSlowlyAsync()); 
taskList.Add(GetVideosSlowlyAsync()); 
taskList.Add(GetVideosSlowlyAsync()); 
taskList.Add(GetVideosSlowlyAsync()); 

Task.WaitAll(taskList.ToArray()) 
foreach (Task task in taskList) 
    vm.Messages.Add(task.Result.Item1);