MediatR会按顺序还是并行运行命令?

4

我在一个应用程序中使用MediatR和CQRS。以下两个语句存在于许多模块中,并且可能在应用程序中同时调用(这是一个Blazor应用程序)。

await Mediator.Send(new AddIdCommand { Id = id });

并且

await Mediator.Send(new DeleteIdCommand { Id = id });

以下是更新同一文本文件的命令。
public class AddIdCommand : IRequest
{
    public int Id { get; set; }

    public class AddIdCommandHandler : IRequestHandler<DeleteIdCommand>
    {
        public async Task<Unit> Handle(AddIdCommand request, CancellationToken cancellationToken)
        {
            // .... update the text file with the Id deleted
        }
    }
}

public class DeleteIdCommand : IRequest
{
    public int Id { get; set; }

    public class DeleteIdCommandHandler : IRequestHandler<DeleteIdCommand>
    {
        public async Task<Unit> Handle(DeleteIdCommand request, CancellationToken cancellationToken)
        {
            // .... update the text file with the Id added
        }
    }
}

 ....
    protected IMediator Mediator => _mediator ??= HttpContext.RequestServices.GetService<IMediator>();
< p >这两个命令中的Handle(...)是否总是按顺序调用?(因此不必担心多个进程更新同一文件的问题。)< /p >

不确定MediatR是什么,但await通常意味着等待,除非底层发生了一些奇怪的事情。 - TheGeneral
这是一个 Blazor 应用程序。可能会有许多用户同时使用网站。此外,语句在各个地方被调用。 - ca9163d9
1个回答

2
“这两行的上下文只能从中推断出:”
await Mediator.Send(new AddIdCommand { Id = id });
await Mediator.Send(new DeleteIdCommand { Id = id });

它将按顺序运行。
你可以在这里看到代码:

https://github.com/jbogard/MediatR/blob/master/src/MediatR/Mediator.cs

var requestType = request.GetType();

var handler = (RequestHandlerWrapper<TResponse>)_requestHandlers.GetOrAdd(requestType,
    t => Activator.CreateInstance(typeof(RequestHandlerWrapperImpl<,>).MakeGenericType(requestType, typeof(TResponse))));

return handler.Handle(request, cancellationToken, _serviceFactory);

它只是返回您异步Handle方法的任务。因此,如果您等待后续的处理方法,它将同步运行(相对于彼此)。
但是您在问题末尾写道:
“因此,不需要担心多个进程更新相同文件的问题。”
我对此并不确定。即使您等待发送两种方法,如果有两个独立的进程调用这两种方法,而且它们都针对相同的文件,它们之间的顺序也无法得到保证。 Mediator.cs为多线程应用程序所做的唯一同步是_concurrentDictionary。因此,它保证此行永远不会为同一类型初始化多个处理程序,即使在并行调用时也是如此:
var handler = (RequestHandlerWrapper<TResponse>)_requestHandlers.GetOrAdd(requestType,
        t => Activator.CreateInstance(typeof(RequestHandlerWrapperImpl<,>).MakeGenericType(requestType, typeof(TResponse))));

"Handle调用没有同步。"

实际上,在调用您的处理方法之前,它首先经过RequestHandlerWrapper,但是您可以查看其实现,它似乎没有同步。 - Erndob
没关系,“它们之间的顺序不能保证”这一点。看起来我需要使用 lock {} 或者队列来同步执行。 - ca9163d9
事件呢?同一事件的多个事件处理器也是按顺序运行吗? - diegosasw

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接