Delegate.BeginInvoke vs ThreadPool.QueueWorkerUserItem - PullRequest
6 голосов
/ 20 апреля 2011
    public void BeforeSendReply(ref Message reply, object correlationState)
    {
        var replyCopy = reply;

        ThreadPool.QueueUserWorkItem(delegate
        {
            RequestQueueHandler.RequestQueue.Add((Message)correlationState, replyCopy);
        });
    }

против

    private delegate void RequestQueueHandlerAdd(Message request, Message reply);

    private static void AsyncMethod(Message request, Message reply)
    {
        RequestQueueHandler.RequestQueue.Add(request, reply);
    }

    public void BeforeSendReply(ref Message reply, object correlationState)
    {
        ((RequestQueueHandlerAdd)AsyncMethod).BeginInvoke((Message)correlationState, reply, null, null);
    }

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

Я склонен к ThreadPool.QueueWorkerUserItem, но я понятия не имею, какой из них на самом деле лучше, ни в этом случае, ни в целом

UPDATE

Я читал кое-что о TPL .. выяснил это:

    public void BeforeSendReply(ref Message reply, object correlationState)
    {
        var replyCopy = reply;
        var enqueue = Task.Factory.StartNew(() => RequestQueueHandler.RequestQueue.Add((Message)correlationState, replyCopy));

    }

как я должен обрабатывать исключение здесь? Я имею в виду, если я сделаю

    public void BeforeSendReply(ref Message reply, object correlationState)
    {
        var replyCopy = reply;
        var enqueue = Task.Factory.StartNew(() => RequestQueueHandler.RequestQueue.Add((Message) correlationState, replyCopy));

        **try
        {
            enqueue.Wait();
        }
        catch(AggregateException e)
        {
            Handle(e);
        }**
    }

Не упустил ли я здесь смысл параллелизма?

Разве я не должен просто обработать возможный выброс исключения в методе RequestQueueHandler.RequestQueue.Add?

Ответы [ 3 ]

3 голосов
/ 20 апреля 2011

В методе Delegate.BeginInvoke() также используется ThreadPool, поэтому не ожидайте какой-либо значимой разницы в производительности.

QueueUserWorkItem() напрямую не лучше, просто проще в большинстве случаев.

Но обратите внимание, что оба примера отсутствуют. Обработка ошибок.
Вашему хорошему короткому делегату нужна попытка / отлов, сценарий BeginInvoke - обратный вызов.

Поэтому, когда вы можете использовать Fx4, вам следуетиспользуйте TPL для гораздо более высокого уровня абстракции.

2 голосов
/ 20 апреля 2011

Асинхронные делегаты дают вам немного больше: возвращаемые значения и пересылку исключений (вы должны вызвать EndInvoke, чтобы получить к ним доступ).При непосредственном использовании ThreadPool вы должны позаботиться об этом сами.

Преимущество ThreadPool с другой стороны - простота.

Посмотрите на эту превосходную онлайн книгу ,в котором подробно рассматриваются два (и более) подхода.

Как правило:

  • используйте TPL, если вы можете
  • , если не используете ThreadPool напрямуюдля простых задач запуска и забывания
  • , если не использовать асинхронные делегаты
1 голос
/ 20 апреля 2011

ThreadPool.QueueWorkerUserItem является более высоким уровнем и предпочтительнее. Но ThreadPool.QueueWorkerUserItem за сценой использует Delegate.BeginInvoke. Но Delegate.BeginInvoke использует потоки из ThreadPool.

...