这是我之前的问题的演变。回顾一下,我需要使用第 3 方 WebSocket,其中请求以一种方法发送,响应以另一种方法给出。我正在尝试将其转换为Task
.
我阅读了这篇 MSDN 杂志文章,其中展示了一个使用 aSemaphoreSlim
来控制条目的示例,但我的情况并不完全相同,我不确定最好的做法是什么。
我可以将它放在文章中所示SemaphoreSlim.Release()
的finally
块中GetPositionsAsync()
,但是如果出现错误,那么 finally 可能会在之前被调用,如果有另一个线程在等待信号量positionEnd()
,则会导致错误。GetPositionsAsync()
另一方面,如果我放入,SemaphoreSlim.Release()
我positionEnd()
可以可靠地假设它GetPositionsAsync()
会返回正确的结果吗?我担心如果释放发生,一个等待信号量的线程可能会Positions.Clear()
在另一个线程保存 to 的值之前Positions
调用result
。所以无论哪种方式,实际上都是同样的担忧。哪个更好,或者有其他方法可以保护这个问题不一起发生?
这是我目前所拥有的......
private TaskCompletionSource<List<Position>> PositionsTaskSource { get; set; }
private readonly SemaphoreSlim PositionsMutex = new(1, 1);
public async Task<List<Position>> GetPositionsAsync()
{
try
{
await PositionsMutex.WaitAsync().ConfigureAwait(false);
Positions.Clear();
PositionsTaskSource = new();
IbWebSocket.reqPositions();
var result = await PositionsTaskSource.Task;
//Write to Trace Log here
return result;
}
finally
{
//I could put the Release here as shown in the article
//PositionsMutex.Release();
}
}
/// <summary>
/// Provides a position to the reqPositions() method. When the last position has been received positionEnd() is called.
/// </summary>
/// <param name="account"></param>
/// <param name="contract"></param>
/// <param name="value"></param>
public void position(string account, Contract contract, double value)
{
Positions.Add(new Position(account, contract, value));
}
/// <summary>
/// Indicates all the positions have been transmitted.
/// </summary>
public void positionEnd()
{
PositionsTaskSource.TrySetResult(Positions))
PositionsMutex.Release();
}