如何将此WebSocket模式转换为我可以等待/取消/继续执行的任务/
我需要使用第三方WebSocket,其中请求以一种方法发送,响应以另一种方法给出。如何将这种模式转换为更典型的异步/等待TPL任务,该任务将支持取消(通过令牌)、继续和所有其他功能 这就是我到目前为止提出的,尽管我不确定它是否有效。我要到星期一才能测试 下面是我的问题:如何将此WebSocket模式转换为我可以等待/取消/继续执行的任务/,websocket,async-await,task-parallel-library,ienumerable,taskcompletionsource,Websocket,Async Await,Task Parallel Library,Ienumerable,Taskcompletionsource,我需要使用第三方WebSocket,其中请求以一种方法发送,响应以另一种方法给出。如何将这种模式转换为更典型的异步/等待TPL任务,该任务将支持取消(通过令牌)、继续和所有其他功能 这就是我到目前为止提出的,尽管我不确定它是否有效。我要到星期一才能测试 下面是我的问题: 这样行吗 我一直在读关于TaskCompletionSource。有没有更好的方法可以通过TaskCompletionSource实现这些功能 我真的不喜欢锁,因为我知道它可能会阻塞很长一段时间,但我不确定如何做得更好,因为
TaskCompletionSource
。有没有更好的方法可以通过TaskCompletionSource
实现这些功能
AsyncGetPositions
的第二次调用,可能会清除已返回的任何位置
锁
我也知道,如果超时或取消导致问题,那么我可能只是删除取消令牌。我唯一能想到的另一件事是创建多个客户端,这些客户端都经过身份验证并准备好处理请求,然后像线程池一样管理它们,以处理这些类型的请求,但我不会很快这么做,所以除此之外。。。idk
private object GetPositionsLock = new object();
private IEnumerable<Position> Positions { get; } = new List<Position>();
private Task PositionsReturned { get; set; }
public async Task<List<Position>> AsyncGetPositions(CancellationToken token)
{
try
{
lock (GetPositionsLock)
{
Positions.Clear();
IbWebSocket.reqPositions();
PositionsReturned = new Task(null, token, TaskCreationOptions.None);
PositionsReturned.GetAwaiter().GetResult();
return token.IsCancellationRequested ? null : Positions.ToList().Where(x => x.Shares != 0).ToList();
}
}
catch (TimeoutException ex)
{
//LogTimeout
throw;
}
catch (Exception ex)
{
//LogError
throw;
}
}
/// <summary>
/// Provides a position to the reqPositions() method. When the last position has been received positionEnd() is called.
/// </summary>
/// <param name="contract"></param>
/// <param name="value"></param>
/// <param name="account"></param>
public void position(string account, Contract contract, double value)
{
try
{
Positions.Concat(new Position(account, contract, value));
}
catch (Exception ex)
{
//LogError
throw;
}
}
/// <summary>
/// Indicates all the positions have been transmitted.
/// </summary>
public void positionEnd()
{
PositionsReturned = Task.CompletedTask;
}
private object GetPositionsLock=new object();
私有IEnumerable位置{get;}=new List();
私有任务位置返回{get;set;}
公共异步任务AsyncGetPositions(CancellationToken令牌)
{
尝试
{
锁定(GetPositionsLock)
{
位置。清除();
IbWebSocket.reqPositions();
PositionsReturn=新任务(null,token,TaskCreationOptions.None);
PositionsReturned.GetAwaiter().GetResult();
return token.IsCancellationRequested?null:Positions.ToList()。其中(x=>x.Shares!=0)。ToList();
}
}
捕获(TimeoutException例外)
{
//日志超时
投掷;
}
捕获(例外情况除外)
{
//对数误差
投掷;
}
}
///
///为reqPositions()方法提供位置。当接收到最后一个位置时,调用positionEnd()。
///
///
///
///
公共无效位置(字符串帐户、合同、双倍值)
{
尝试
{
职位:Concat(新职位(账户、合同、价值));
}
捕获(例外情况除外)
{
//对数误差
投掷;
}
}
///
///表示所有位置都已传输。
///
公共关系结束()
{
位置返回=Task.CompletedTask;
}
lock
与async
代码一起使用,或者
我一直在读关于TaskCompletionSource的文章。有没有更好的方法可以通过TaskCompletionSource实现这些功能
是的,这是用于此场景的类型
我真的不喜欢锁,因为我知道它可能会阻塞很长一段时间,但我不确定如何做得更好,因为如果我不锁定对AsyncGetPositions的第二次调用,可能会清除已返回的任何位置
我建议先让它工作起来,然后再处理重新进入的附加要求。每一个都已经够难了
您要做的是创建一个
TaskCompletionSource
,并在调用positionEnd
时完成它。为简单起见,开始时不要考虑重入问题,也不要使用CancellationToken
。一旦您完全理解了TaskCompletionSource
,您就可以增加复杂性:
private List<Position> Positions { get; } = new();
private TaskCompletionSource<List<Position>> PositionsReturned { get; set; }
public Task<List<Position>> AsyncGetPositions()
{
Positions.Clear();
PositionsReturned = new();
IbWebSocket.reqPositions();
return PositionsReturned.Task;
}
public void position(string account, Contract contract, double value)
{
Positions.Add(new Position(account, contract, value));
}
public void positionEnd()
{
PositionsReturned.TrySetResult(Positions);
}
私有列表位置{get;}=new();
私有TaskCompletionSource位置返回{get;set;}
公共任务AsyncGetPositions()
{
位置。清除();
位置返回=新();
IbWebSocket.reqPositions();
返回位置返回任务;
}
公共无效位置(字符串帐户、合同、双倍值)
{
职位。添加(新职位(账户、合同、价值));
}
公共关系结束()
{
位置返回。TrySetResult(位置);
}
这样行吗
不可以。您可以将lock
与async
代码一起使用,或者
我一直在读关于TaskCompletionSource的文章。有没有更好的方法可以通过TaskCompletionSource实现这些功能
是的,这是用于此场景的类型
我真的不喜欢锁,因为我知道它可能会阻塞很长一段时间,但我不确定如何做得更好,因为如果我不锁定对AsyncGetPositions的第二次调用,可能会清除已返回的任何位置
我建议先让它工作起来,然后再处理重新进入的附加要求。每一个都已经够难了
您要做的是创建一个
TaskCompletionSource
,并在调用positionEnd
时完成它。为简单起见,开始时不要考虑重入问题,也不要使用CancellationToken
。一旦您完全理解了TaskCompletionSource
,您就可以增加复杂性:
private List<Position> Positions { get; } = new();
private TaskCompletionSource<List<Position>> PositionsReturned { get; set; }
public Task<List<Position>> AsyncGetPositions()
{
Positions.Clear();
PositionsReturned = new();
IbWebSocket.reqPositions();
return PositionsReturned.Task;
}
public void position(string account, Contract contract, double value)
{
Positions.Add(new Position(account, contract, value));
}
public void positionEnd()
{
PositionsReturned.TrySetResult(Positions);
}
私有列表位置{get;}=new();
私有TaskCompletionSource位置返回{get;set;}
公共任务AsyncGetPositions()
{
位置。清除();
位置返回=新();
IbWebSocket.reqPositions();
返回位置返回任务;
}
公共无效位置(字符串帐户、合同、双倍值)
{
职位。添加(新职位(账户、合同、价值));
}
公共关系结束()
{
位置返回。TrySetResult(位置);
}
不确定从哪里开始AsyncGetPositions
甚至没有执行asyn调用(我没有看到任何Wait
语句)。此外,您实际上并不启动任务
。还有,什么是套接字接口?这些活动看起来怎么样?不知道从哪里开始AsyncGetPositions
甚至不在