我目前正在开发一个小型服务器应用程序并掌握Task<>以及其他相关操作。
我想知道阻止操作在任务中是如何工作的。
因此,例如,我目前使用几个具有“阻塞”操作的库。其中一个是Npgsql(PostgreSQL提供程序。)
如果我执行以下操作......
Task myTask = new Task<>( () =>
{
using(var db = new PostgresqlDatabaseConnection())
{
db.ExecuteQuery("SELECT takes 50 ms to get data...")
db.Insert(anObject); etc....
}
}
).Start();
并说,将其链接到处理该数据的许多其他任务。
这是否有效? I.E.假设ExexuteQuery调用某种Thread.Sleep(1)或以某种方式阻塞线程,这是否会影响我的任务执行?
我问,因为我的服务器使用了几个必须重写的库来容纳完全异步的方法。 或者这个Async足够吗?
* 我的想法*
我真的不确定。
我知道,例如,如果db.Executre()只运行了一个while(true)循环,直到得到它的数据,它几乎肯定会阻塞我的服务器。因为很多时候会花费处理(真实)。或者Task是否足够聪明,知道它应该花更少的时间在这上面?或者,如果内部使用一些等待机制,那么Task库是否知道?是否知道应该在等待时处理其他任务。
答案 0 :(得分:3)
使用C#5的async / await功能肯定会让事情变得更容易。它可以使异步代码更容易编写,因为你编写的代码非常类似于编写同步代码的方式。
采用以下示例。我正在使用Thread.Sleep来模拟长时间运行的操作,因此任何不支持本地异步的库仍然可以通过Task.Run
使用。虽然Thread.Sleep
阻碍了该主题,但您的UI仍然具有响应能力。如果您已同步编写此代码,则在thread.sleep
完成之前,您的UI将保持1.5秒。
private async void button1_Click(object sender, EventArgs e)
{
Console.WriteLine("0");
await DoWorkAsync();
Console.WriteLine("3");
}
private async Task DoWorkAsync()
{
Console.WriteLine("1");
await Task.Run(()=>
{
// Do your db work here.
Thread.Sleep(1500);
});
Console.WriteLine("2");
}
简而言之,如果您有长时间运行的数据库操作并且希望保持UI响应,则应该利用async / await。虽然这确实可以保持您的用户界面响应,但它确实会引入新的挑战:what happens if the user clicks a button multiple times
或what if the user closes the window while you are still processing
来命名一些简单的案例。
我鼓励您进一步阅读有关该主题的内容。 Jon Skeet在异步上有一个multi-part series。关于此主题的MSDN文章也很多:1 2 3 ...
答案 1 :(得分:3)
我目前正在开发一个小型服务器应用程序并开始使用 掌握Task&lt;&gt;以及其他相关操作。
除非并发客户端连接的数量,否则您在服务器端应用程序中使用new Task
,Task.Factory.StartNew
,Task.Run
会受益匪浅真的很低查看this和this了解更多详情。
然而,使用自然异步API会大大受益。他们在飞行中#34;时不会阻塞池线程,因此线程返回到池中,然后可以忙于提供另一个客户端请求。这可以提高您的服务器应用程序可伸缩性。
我不确定PostgreSQL是否提供此类API,请查找ExecuteQueryAsync
或BeginExecuteQuery
/ EndExecuteQuery
之类的内容。如果它没有,只需使用同步ExecuteQuery
方法,但不将其卸载到池线程中,就像在代码片段中一样。
答案 2 :(得分:1)
异步编程无助于提高逻辑或数据库的效率。它只会影响操作之间切换的性能。
您无法更快地将查询或计算包装在Task
中。你只需增加开销。
在服务器上使用Async IO来实现数百个并发请求的可伸缩性。你在这里不需要它。