• Your async handler routine should not exit after each message: Service broker expects its handlers to continue processing messages for as long as there are more messages available. As you discovered, it only rechecks after 5 seconds to see if the queue has emptied. Only if it hasn't then it starts another handler, for as far as the max_queue_readers setting permits it.

    So the problem you need to fix is first of all in your handler procedure. Try this for example (not tested):

    if object_id('usp_AsyncExecActivated') is not null

    drop procedure usp_AsyncExecActivated;

    go

    create procedure usp_AsyncExecActivated

    as

    set nocount on;

    declare @h uniqueidentifier,

    @messageTypeName sysname,

    @messageBody varbinary(max),

    @xmlBody xml,

    @procedureName sysname,

    @startTime datetime,

    @finishTime datetime,

    @token uniqueidentifier;

    while 1 = 1

    begin

    begin tran;

    waitfor(

    receive top(1)

    @h = conversation_handle,

    @messageTypeName = message_type_name,

    @messageBody = message_body

    from AsyncExecQueue

    ), TIMEOUT 5000;

    if not @@rowcount > 0

    begin

    commit tran;

    break; -- exit while 1 = 1

    end

    if (@messageTypeName = N'DEFAULT')

    begin

    select @xmlBody = CAST(@messageBody as xml);

    select @procedureName = @xmlBody.value('(//procedure/name)[1]', 'sysname');

    select @startTime = CURRENT_TIMESTAMP;

    exec(@procedureName);

    select @finishTime = CURRENT_TIMESTAMP;

    select @token = conversation_id

    from sys.conversation_endpoints

    where conversation_handle = @h;

    insert AsyncExecResults (start_time, finish_time, token)

    values(

    @startTime,

    @finishTime,

    @token);

    end

    else if (@messageTypeName = N'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog')

    begin

    end conversation @h;

    end

    commit tran;

    end

    go

    This will process your messages sequentially, until for more than 5 seconds the queue could not be emptied by a single instance. If the queue is not empty 5 seconds after the 1st instance got started a 2nd instance will be started, and 2 messages will be processed simultaneously. Then after 10 seconds and the queue is still not empty, a 3rd instance is started and 3 messages are processed at the same time (provided your server has at least 3 cpu's, otherwise you'll just be context switching) and so on, until either the maximum number of max_queue_readers is reached or the queue becomes empty for at least 5 seconds (= the timeout value on your waitfor( receive) statement).

    In practice 25 queue readers is probably way to high.



    Posting Data Etiquette - Jeff Moden[/url]
    Posting Performance Based Questions - Gail Shaw[/url]
    Hidden RBAR - Jeff Moden[/url]
    Cross Tabs and Pivots - Jeff Moden[/url]
    Catch-all queries - Gail Shaw[/url]


    If you don't have time to do it right, when will you have time to do it over?