14

我正在尝试在 web 服务方法中做一些异步的东西。假设我有以下 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 Web 应用程序中执行后台或分叉线程的错误方式吗?

4

3 回答 3

18

BackgroundWorker当您需要同步回(例如)UI* 线程时很有用,例如出于相似性原因。在这种情况下,似乎简单地使用ThreadPool就足够了(而且更简单)。如果您的流量很大,那么生产者/消费者队列可能会允许更好的节流(这样您就不会淹没在线程中) - 但我怀疑ThreadPool这里会很好......

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

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

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

于 2008-10-23T07:08:48.970 回答
1

再生产者/消费者;基本上 - 只是值得保持某种油门。在最简单的级别上,Semaphore可以使用 a (与常规 一起ThreadPool)将事情限制在已知的工作量内(以避免使线程池饱和);但是生产者/消费者队列可能会更有效率和管理。

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

就是说:如果您正在调用外部网站,您很可能会在网络 IO / 完成端口上等待很多;因此,您可以拥有稍多的线程......显然(相比之下)如果工作受 CPU 限制,那么拥有比 CPU 内核更多的线程是没有意义的。

于 2008-10-27T23:28:20.653 回答
0

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

于 2008-10-23T07:20:03.737 回答