Lod*_*ijk 13 asp.net-mvc asynchronous task-parallel-library
所以我试图了解.net 4.5中这个新的"异步"内容.我之前使用异步控制器和任务并行库进行了一些操作,并完成了这段代码:
采取这个模型:
public class TestOutput
{
public string One { get; set; }
public string Two { get; set; }
public string Three { get; set; }
public static string DoWork(string input)
{
Thread.Sleep(2000);
return input;
}
}
Run Code Online (Sandbox Code Playgroud)
在这样的控制器中使用哪个:
public void IndexAsync()
{
AsyncManager.OutstandingOperations.Increment(3);
Task.Factory.StartNew(() =>
{
return TestOutput.DoWork("1");
})
.ContinueWith(t =>
{
AsyncManager.OutstandingOperations.Decrement();
AsyncManager.Parameters["one"] = t.Result;
});
Task.Factory.StartNew(() =>
{
return TestOutput.DoWork("2");
})
.ContinueWith(t =>
{
AsyncManager.OutstandingOperations.Decrement();
AsyncManager.Parameters["two"] = t.Result;
});
Task.Factory.StartNew(() =>
{
return TestOutput.DoWork("3");
})
.ContinueWith(t =>
{
AsyncManager.OutstandingOperations.Decrement();
AsyncManager.Parameters["three"] = t.Result;
});
}
public ActionResult IndexCompleted(string one, string two, string three)
{
return View(new TestOutput { One = one, Two = two, Three = three });
}
Run Code Online (Sandbox Code Playgroud)
由于TPL的神奇之处,该控制器可在2秒内渲染视图.
现在我期望(相当天真地)使用C#5的新"异步"和"等待"功能将上面的代码转换为以下代码:
public async Task<ActionResult> Index()
{
return View(new TestOutput
{
One = await Task.Run(() =>TestOutput.DoWork("one")),
Two = await Task.Run(() =>TestOutput.DoWork("two")),
Three = await Task.Run(() =>TestOutput.DoWork("three"))
});
}
Run Code Online (Sandbox Code Playgroud)
此控制器在6秒内呈现视图.在翻译的某处,代码变得不再平行.我知道异步和并行是两个不同的概念,但不知怎的,我认为代码的工作原理是一样的.有人能指出这里发生了什么以及如何解决这个问题?
Ste*_*ary 18
在翻译的某处,代码变得不再平行.
正是.await将(异步)等待单个操作完成.
并行异步操作可以通过启动实际的Tasks 来完成,但await直到稍后才能完成:
public async Task<ActionResult> Index()
{
// Start all three operations.
var tasks = new[]
{
Task.Run(() =>TestOutput.DoWork("one")),
Task.Run(() =>TestOutput.DoWork("two")),
Task.Run(() =>TestOutput.DoWork("three"))
};
// Asynchronously wait for them all to complete.
var results = await Task.WhenAll(tasks);
// Retrieve the results.
return View(new TestOutput
{
One = results[0],
Two = results[1],
Three = results[2]
});
}
Run Code Online (Sandbox Code Playgroud)
PS还有一个Task.WhenAny.
不,你说的原因已经不同了.并行和异步是两回事.
任务版本在2秒内工作,因为它同时运行三个操作(只要你有3个以上的处理器).
await实际上就是它的声音,代码将等待Task.Run的执行,然后再继续下一行代码.
因此,TPL版本和异步版本之间的最大区别在于TPL版本以任何顺序运行,因为所有任务都是相互独立的.然而,异步版本按照编写代码的顺序运行.因此,如果您想要并行,请使用TPL,如果您想要异步,请使用async.
异步的重点是能够编写同步外观代码,在长时间运行的操作发生时不会锁定UI.但是,这通常是所有处理器正在执行的操作正在等待响应.async/await使得调用async方法的代码不会等待异步方法返回,就是这样.所以,如果你真的想用async/await模仿你的第一个模型(我不建议),你可以这样做:
MainMethod()
{
RunTask1();
RunTask2();
RunTask3();
}
async RunTask1()
{
var one = await Task.Factory.StartNew(()=>TestOutput.DoWork("one"));
//do stuff with one
}
async RunTask2()
{
var two= await Task.Factory.StartNew(()=>TestOutput.DoWork("two"));
//do stuff with two
}
async RunTask3()
{
var three= await Task.Factory.StartNew(()=>TestOutput.DoWork("three"));
//do stuff with three
}
Run Code Online (Sandbox Code Playgroud)
代码路径将是这样的(如果任务长时间运行)
****虽然这是一个很大的免责声明.如果任务在await被命中时已经完成,则Await将同步运行.这节省了运行时不必执行其vudu :),因为它不需要.这将使上面的代码流不正确,因为流现在是同步的****
Eric Lippert关于此的博文解释了比我正在做的更好的事情:) http://blogs.msdn.com/b/ericlippert/archive/2010/10/29/asynchronous-programming-in-c-5-0-部分两何处,await.aspx
希望这有助于消除您关于异步与TPL的一些问题?最重要的是,异步不是平行的.
| 归档时间: |
|
| 查看次数: |
7835 次 |
| 最近记录: |