异步调用与多线程

时间:2011-06-01 12:41:24

标签: .net asynchronous windows-services

我在VB.NET中有一个Windows服务,它按顺序调用几个长时间运行的进程(常规子例程,而不是web svc,远程处理或任何花哨的东西)。我试图实现多线程只是因为我们以前从未这样做过,这是使命的crticial代码。我想到了异步调用例程。我对此很熟悉并将其用作某些Web服务的一部分。我错过了什么吗?似乎asynch调用是避免多线程问题的“穷人”方式。

3 个答案:

答案 0 :(得分:1)

异步调用通常比常规多线程更好,因为它们利用IO COmpletion Ports线程,这在CPU使用方面更有效。

答案 1 :(得分:1)

  

似乎asynch调用是避免多线程问题的“穷人”方式。

不一定。 Javascript(以及像Node.js这样的Javascript的服务器变体)在单个线程上运行,但是利用了大量的异步,因此没有多少时间等待长时间运行的操作完成。这是优化单个线程的一种方式,如果你有正确的心态,它可以是一种非常强大的编程方式。

如果您对异步编程感到满意,那就去吧!由于任务可以并行化,因此无需引入大量线程。

但是,如果任务是CPU绑定的,那么单个线程将会阻塞,并且由于显而易见的原因,异步将无法帮助您。如果任务是IO,那么异步可能是要走的路。

编辑:

抱歉,我不清楚。我认为CPU绑定的意思是,如果某个特定操作使用了大量CPU,则该线程将不断使用,并且不可用于其他任务。

例如:

// task
long sum = 0;
for (int i = 0; i < 1000000; i++)
    for (int j = 1000000; j > 0; j--)
         sum = i + j;

如果需要两次运行上面的代码,使用一个线程的异步模型将无济于事,因为单个线程将不断为整个任务工作。如果你有两个线程,两者都可以在同一时间执行。

// task
List<string> urls = GetListOfUrls();
List<string> html = new List<string>();
foreach (var url in urls) 
{
    GetUrlAsync(url, callback: (data) => html.Add(data) );
}

上述任务是IO任务。该方法中的大部分时间将用于等待HTTP请求,而不是使用CPU。如果此任务是同步的,则单个线程将具有与第一个相同的症状。如果它是异步的,在等待HTTP请求完成时,该线程可以做更多工作,比如启动另一个URL下载。

因此,如果您的任务将花费大量时间等待外部进程,请使用异步。任务是否会烧掉cpu,使用多个线程。

答案 2 :(得分:1)

我不知道您希望通过异步调用避免多线程问题。异步调用多线程。唯一真正的区别是异步调用通常用于相对短暂的任务,而传统的多线程(显式创建线程并启动它运行)通常用于长时间运行的任务。

无论哪种方式,您仍然会遇到相同的并发问题。

可以使用异步调用来执行长时间运行的任务。实际上,Task类有一个构造函数,可让您指定creation options,包括TaskCreationOptions.LongRunning

使用Thread类管理自己的线程比使用TaskThreadPool.QueueUserWorkItem之类的东西要复杂一点,但它也会让您稍微控制一下。无论如何,您必须处理并发问题,如竞争条件和线程安全数据结构(如果多个线程正在修改数据结构)。我不会将异步调用称为“穷人的多线程”。差异并不大。他们只是两种不同的方式来完成同样的事情。