[英]Is using AutoResetEvent across async block code safe?
我試圖鎖定我的同步代碼部分並釋放異步代碼塊中的鎖(在執行任務后)。 我已經閱讀了“AutoResetEvent”,並希望在代碼實現的調用者和被調用者之間實現其信號功能。
目的是鎖定負責驗證之前是否管理過事務的代碼。 檢查完成並保存交易后,我發布代碼。 檢查和保存操作是異步的,鎖釋放發生在'continueWith'委托function。
我有以下 AutoResetEvent 的抽象和實現:
public interface IThreadLockKeyProvider { public AutoResetEvent PayLock { get; } }
public class ThreadLockKeyProvider : IThreadLockKeyProvider
{
public static readonly AutoResetEvent _payLock;
static ThreadLockKeyProvider()
{
_payLock = new AutoResetEvent(true);
}
public AutoResetEvent PayLock { get { return _payLock; } }
}
該實例作為 singleton 注入到 .net 核心依賴注入容器中。
事件處理方法的代碼如下:
public Task<Unit> Handle(ProcessPaymentCommand command, CancellationToken cancellationToken)
{
_threadLockKeyProvider.PayLock.WaitOne();
var res = _brandDepositStrategy.AdministerDeposit().Result;
return Task.FromResult(Unit.Value);
}
釋放鎖的 AdministerDeposit 方法。
public override async Task<Task> AdministerDeposit()
{
Task<PaymentTransactions> dbOperation = _transactionAdministrationFacade.UpdateDbTransactionAsync(_IPNRequestDto);
return await dbOperation.ContinueWith(async x =>
{
_threadLockKeyProvider.PayLock.Set();
if (x.IsFaulted)
throw x.Exception;
_transactionAdministrationFacade.CallBackDto = await _responseComposer.GetPaymentResponseDto(x.Result, _IPNRequestDto);
await CreateDepositSF();
});
}
問題是執行會不會有什么問題?
注意:代碼確實有效。 它不會崩潰並通過我構建的單元測試。
理論上,在這種情況下AutoResetEvent
沒有任何問題,但是:它並不是完全為異步構建的,這意味着您的WaitOne()
阻塞了一個線程——這正是您要避免的。 同樣,您正在使用異步同步。 因為這基本上是一個異步鎖,所以看到入口/出口相距如此之遠讓我很擔心——這很容易引入錯誤。
讓我們嘗試解決這些問題:
SemaphoreSlim
作為異步友好鎖await
我們的結果例子:
private readonly SemaphoreSlim _lock = new(1, 1);
public async Task<int> SomeOuterMethodAsync(CancellationToken cancellationToken)
{
await _lock.WaitAsync(cancellationToken);
try
{
var s = await SomeInnerMethodAsync(cancellationToken);
return s.Length; // just some projection
}
finally
{
_lock.Release();
}
}
// note: this could be in unrelated types/instances/etc
private Task<string> SomeInnerMethodAsync(CancellationToken cancellationToken)
=> throw new InvalidOperationException("not shown");
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.