.NET Web服务和BackgroundWorker线程

我正试图在webservice方法中做一些异步的东西。 假设我有以下API调用: http : //www.example.com/api.asmx

并且该方法称为GetProducts()

我这个GetProducts方法,我做了一些事情(例如从数据库中获取数据)然后在我返回结果之前,我想做一些异步的东西(例如给我发电子邮件)。

所以这就是我所做的。

[WebMethod(Description = "Bal blah blah.")] public IList GetProducts() { // Blah blah blah .. // Get data from DB .. hi DB! // var myData = ....... // Moar clbuttic blahs :) (yes, google for clbuttic if you don't know what that is) // Ok .. now send me an email for no particular reason, but to prove that async stuff works. var myObject = new MyObject(); myObject.SendDataAsync(); // Ok, now return the result. return myData; } } public class TrackingCode { public void SendDataAsync() { var backgroundWorker = new BackgroundWorker(); backgroundWorker.DoWork += BackgroundWorker_DoWork; backgroundWorker.RunWorkerAsync(); //System.Threading.Thread.Sleep(1000 * 20); } private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e) { SendEmail(); } } 

现在,当我运行此代码时,电子邮件永远不会发送。 如果我取消注释Thread.Sleep ..然后发送电子邮件。

那么……为什么背景工作者线程被拆除了? 它依赖于父线程吗? 这是我在asp.net网络应用程序中做背景或分叉线程的错误方法吗?

当您需要同步回(例如)UI *线程时, BackgroundWorker很有用,例如出于亲和力原因。 在这种情况下,似乎只使用ThreadPool就足够了(而且更简单)。 如果你的数量很大,那么生产者/消费者队列可能允许更好的限制(所以你不要淹没在线程中) – 但我怀疑ThreadPool在这里会好的……

 public void SendDataAsync() { ThreadPool.QueueUserWorkItem(delegate { SendEmail(); }); } 

另外 – 我不太确定你想通过睡觉达到什么目的? 这只会占用一个线程(不使用CPU,但也没有好处)。 注意详细说明? 看起来你正在暂停你的实际网页(即睡眠发生在网页线程,而不是电子邮件线程)。 你想在这做什么?

* =实际上,它将使用任何同步上下文

再生产者/消费者; 基本上 – 这是值得保持某种油门。 在最简单的层面上,可以使用Semaphore (以及常规的ThreadPool )将事物限制为已知的工作量(以避免使线程池饱和); 但生产者/消费者队列可能会更有效率和管理。

Jon Skeet 在这里有一个这样的队列( CustomThreadPool )。 如果你愿意,我可能会写一些关于它的笔记。

这就是说:如果你正在呼叫一个外部网站,你很可能会在网络IO /完成端口上有很多等待; 因此,您可以拥有稍高的线程数……显然(相比之下)如果工作受CPU限制,那么没有任何一点比您拥有CPU内核更多的线程。

它可能会被拆除,因为在20秒之后,BackgroundWorker实例可能会被垃圾收集,因为它没有引用(超出范围)。