.NET Web Service & BackgroundWorker темы - PullRequest
14 голосов
/ 23 октября 2008

Я пытаюсь сделать что-то асинхронное в методе веб-сервиса. Допустим, у меня есть следующий вызов 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?

Ответы [ 3 ]

17 голосов
/ 23 октября 2008

BackgroundWorker полезно, когда вам нужно синхронизировать обратно (например) с потоком пользовательского интерфейса *, например, по причинам близости. В этом случае может показаться, что просто использовать ThreadPool было бы более чем достаточно (и намного проще). Если у вас большие объемы, то очередь производителя / потребителя может позволить лучше регулировать (чтобы вы не тонули в потоках) - но я подозреваю, что ThreadPool здесь будет хорошо ...

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

Кроме того - я не совсем уверен, чего ты хочешь достичь, спя? Это просто свяжет поток (не использует процессор, но тоже ничего не даст). Хотите разработать? Это выглядит , как будто вы приостанавливаете свою реальную веб-страницу (т.е. спящий процесс происходит в потоке веб-страницы, а не в потоке электронной почты). Что ты здесь пытаешься сделать?

* = на самом деле, он будет использовать любой синхронизирующий контекст на месте

1 голос
/ 28 октября 2008

Ре производитель / потребитель; в основном - просто стоит сохранить какой-то вид газа. На простейшем уровне можно использовать Semaphore (наряду с обычным ThreadPool), чтобы ограничить объемы до известного объема работы (чтобы избежать насыщения пула потоков); но очередь производителя / потребителя, вероятно, будет более эффективной и управляемой.

У Джона Скита такая очередь здесь (CustomThreadPool). Я мог бы написать несколько заметок об этом, если хотите.

Тем не менее, если вы звоните на внешний веб-сайт, вполне вероятно, что у вас будет много ожиданий на сетевых портах ввода / вывода; таким образом, у вас может быть немного большее количество потоков ... очевидно (в отличие от этого), если работа была связана с ЦП, нет смысла иметь больше потоков, чем у вас ядер ЦП.

0 голосов
/ 23 октября 2008

Он может быть снесен, потому что через 20 секунд этот экземпляр BackgroundWorker может быть подвергнут сборке мусора, поскольку у него нет ссылок (ушел из области видимости).

...