0

AsyncDemoViewModel で Messages プロパティの文字列リストを出力しています。

GetVideosSlowlyAsync() で Thread.Sleep(1000) を使用すると、出力は

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

GetVideosSlowlyAsync() で await Task.Delay(1000) を使用すると、出力は

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());
    }

}
4

2 に答える 2

3

await メソッドは、GetVideosSlowlyAsync メソッドが完了するのを待ちます。操作の結果が必要な場所に await を移動する必要があります。

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);
}
于 2012-11-03T23:21:37.013 に答える
0

await GetVideosSlowlyAsync()タスクが終了するまで、呼び出し元のメソッドに戻る呼び出しを行っています。期待する結果を見たい場合は、この await を削除する必要があります。このようにして、メソッドがスレッドプールでスリープしているGetVideosSlowlyAsync()間に、4 つすべてを次々に開始します。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);
于 2012-11-03T23:16:37.963 に答える