我正在尝试在webservice方法中做一些异步的东西。假设我有以下API调用:http://www.example.com/api.asmx
,该方法称为 GetProducts()。
我这个GetProducts方法,我做了一些事情(例如从数据库中获取数据)然后在我返回结果之前,我想做一些异步的东西(例如给我发电子邮件)。
所以这就是我所做的。
[WebMethod(Description = "Bal blah blah.")]
public IList<Product> 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网络应用程序中应该做背景或分叉线程的错误方法吗?
答案 0 :(得分:17)
BackgroundWorker
非常有用,例如出于亲和力原因。在这种情况下,似乎只使用ThreadPool
就足够了(而且更简单)。如果你的数量很大,那么生产者/消费者队列可能允许更好的限制(所以你不会淹没在线程中) - 但我怀疑ThreadPool
在这里会没事......
public void SendDataAsync()
{
ThreadPool.QueueUserWorkItem(delegate
{
SendEmail();
});
}
另外 - 我不太确定你想通过睡觉达到什么目的?这只会占用一个线程(不使用CPU,但也没有好处)。注意详细说明? 看起来就像你正在暂停你的实际网页(即睡眠发生在网页线程,而不是电子邮件线程)。你想在这做什么?
* =实际上,它将使用任何同步上下文
答案 1 :(得分:1)
生产者/消费者;基本上 - 只是值得保持一些类型的油门。在最简单的级别,可以使用Semaphore
(与常规ThreadPool
一起)将事物限制为已知的工作量(以避免使线程池饱和);但是生产者/消费者队列可能会更有效率和管理。
Jon Skeet有这样一个队列here(CustomThreadPool
)。如果你愿意,我可能会写一些关于它的笔记。
那就是说:如果你要打电话到外部网站,你很可能会在网络IO /完成端口上等待很多;因此,你可以拥有更高数量的线程......显然(相比之下)如果工作受CPU约束,那么没有任何一点比你拥有CPU内核更多的线程。
答案 2 :(得分:0)
它可能会被拆除,因为在20秒之后,BackgroundWorker实例可能会被垃圾收集,因为它没有引用(超出范围)。