Pergunta

Eu estou tentando fazer algumas coisas assíncrona em um método de serviço Web. Vamos dizer que eu tenho a seguinte chamada de API: http://www.example.com/api.asmx

e o método é chamado GetProducts () .

I Este GetProducts métodos, eu faço algumas coisas (por exemplo. Obter dados de banco de dados), em seguida, pouco antes de eu retornar o resultado, quero fazer algumas coisas assíncrono (ex. Enviar-me um email).

Então é isso que eu fiz.

[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();
    }
}

Agora, quando eu executar esse código o e-mail nunca é enviada. Se eu descomente a Thread.Sleep .. então o e-mail é enviado.

Então ... por que é que o segmento de trabalho de fundo é demolida? é dependente do segmento pai? É este o caminho errado eu deveria estar fazendo fundo ou enfiar bifurcada, em aplicativos da Web ASP.NET?

Foi útil?

Solução

BackgroundWorker é útil quando você precisa sincronizar de volta para (por exemplo) uma interface de usuário * fio, por exemplo, por razões de afinidade. Neste caso, parece que simplesmente usando ThreadPool seria mais do que suficiente (e mais simples). Se você tem altos volumes, em seguida, uma fila de produtor / consumidor pode permitir uma melhor aceleração (para que você não se afogar em threads) - mas eu ThreadPool suspeito vai ficar bem aqui ...

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

Também - Eu não tenho certeza do que você quer alcançar por dormir? Isso só vai amarrar um fio (sem uso de CPU, mas não fazendo o bem, quer). Cuidado ao elaborar? É aparência como você está parando sua página web real (ou seja, o sono acontece no segmento de web-página, e não o fio e-mail). O que você está tentando fazer aqui?

* = realmente, ele irá usar qualquer sincronização ao contexto está no lugar

Outras dicas

Re produtor / consumidor; basicamente - é apenas vale a pena manter alguns tipo de acelerador. No nível mais simples, um Semaphore poderia ser usado (junto com o ThreadPool regular) às coisas limitar a um montante conhecido de trabalho (para evitar a saturação do pool de threads); mas uma fila de produtor / consumidor provavelmente seria mais eficiente e gerenciado.

Jon Skeet tem como uma fila aqui (CustomThreadPool). Eu provavelmente poderia escrever algumas notas sobre isso, se você queria.

Dito isto: se você estiver ligando fora a um web-site externo, é bastante provável que você vai ter um monte de espera na rede portas IO / conclusão; como tal, você pode ter um número ligeiramente maior de tópicos ... obviamente (pelo contrário) se o trabalho foi CPU-bound, não há nenhum ponto de ter mais fios do que você tem núcleos de CPU.

Pode demolido porque depois de 20 segundos, essa instância BackgroundWorker pode ser lixo coletado porque não tem referências (fora do escopo).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top