我在应用程序中使用MediatR和CQRS。以下两个语句存在于许多模块中,并且可以在应用程序(这是一个出色的应用程序)中并发调用。
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>();
两个命令中的Handle(...)
是否总是按顺序调用? (因此,无需担心多个进程会更新同一文件的问题。)
嗯,仅从这两行的上下文来看:
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方法的任务。因此,如果您等待后续的handle方法,则该方法将同步运行(彼此相对)。
但是您用]结束了问题>
因此无需担心多个进程更新同一文件问题。
而且我不确定。即使您正在等待两个发送方法,如果有两个独立的过程调用这两个方法,并且它们都针对同一文件,则它们之间的顺序将无法得到保证。Mediator.cs对多线程应用程序所做的唯一同步是_requestHandlers是ConcurrentDictionary。
因此,即使并行调用,它也保证该行永远不会初始化同一类型的多个处理程序:
var handler = (RequestHandlerWrapper<TResponse>)_requestHandlers.GetOrAdd(requestType, t => Activator.CreateInstance(typeof(RequestHandlerWrapperImpl<,>).MakeGenericType(requestType, typeof(TResponse))));
句柄调用未同步。