【问题标题】:.NET Web Service & BackgroundWorker threads.NET Web 服务和 BackgroundWorker 线程
【发布时间】:2008-10-23 06:54:59
【问题描述】:

我正在尝试在 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 网络应用程序中执行后台或分叉线程的错误方式吗?

【问题讨论】:

    标签: c# asp.net multithreading backgroundworker


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 睡眠被注释掉了。我把它放在那里,看看我是否可以发送电子邮件。当休眠未注释时,则执行后台工作线程代码。当代码被注释掉时,后台工作线程代码永远不会被执行。我会尝试改用 ThreadPool。
    • > 如果你的流量很大,那么生产者/消费者队列可能会允许更好的节流(这样你就不会淹没在线程中) ooooooo!!!我很高兴你真的提出了这一点!网络服务方式其实是大容量!另外,为了让事情变得非常有趣,它并不是真正发送电子邮件,而是实际访问另一个外部网站(ekk,不要问)......所以你会建议我做这个生产者/消费者队列的事情吗?如果是这样......这是一个很好的参考页面吗? albahari.com/threading/part4.aspx(请向下滚动到代码+示例)。想法?
    • @Marc Gravell 我尝试过使用您的解决方案,但我只是想知道为什么完成任务需要太多时间。
    • @AnandMohanAwasthi er....您的具体任务是什么?异步运行它并没有让它更快......
    • @MarcGravell:例如,假设我需要向 2000 个具有相同内容的 id 发送邮件。如果我使用经典方式 on_click 事件执行此操作,则此活动大约需要 5-6 分钟时间,但如果我使用 ThreadPool QueueUserWorkItem 委托,那么它真的需要很长时间......(新处理线程)..请帮助
    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 请注意 Sleep() 在网页线程上; BackgroundWorker 更有可能尝试使用被 Sleep() 本身阻止的同步上下文
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-29
      • 1970-01-01
      • 2011-02-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多