阻止任务中的方法

时间:2014-03-18 02:05:43

标签: c# postgresql asynchronous task-parallel-library

我目前正在开发一个小型服务器应用程序并掌握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库是否知道?是否知道应该在等待时处理其他任务。

3 个答案:

答案 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 timeswhat 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 TaskTask.Factory.StartNewTask.Run会受益匪浅真的很低查看thisthis了解更多详情。

然而,使用自然异步API会大大受益。他们在飞行中#34;时不会阻塞池线程,因此线程返回到池中,然后可以忙于提供另一个客户端请求。这可以提高您的服务器应用程序可伸缩性。

我不确定PostgreSQL是否提供此类API,请查找ExecuteQueryAsyncBeginExecuteQuery / EndExecuteQuery之类的内容。如果它没有,只需使用同步ExecuteQuery方法,但将其卸载到池线程中,就像在代码片段中一样。

答案 2 :(得分:1)

异步编程无助于提高逻辑或数据库的效率。它只会影响操作之间切换的性能。

您无法更快地将查询或计算包装在Task中。你只需增加开销。

在服务器上使用Async IO来实现数百个并发请求的可伸缩性。你在这里不需要它。