如何将此WebSocket模式转换为我可以等待/取消/继续执行的任务/

如何将此WebSocket模式转换为我可以等待/取消/继续执行的任务/,websocket,async-await,task-parallel-library,ienumerable,taskcompletionsource,Websocket,Async Await,Task Parallel Library,Ienumerable,Taskcompletionsource,我需要使用第三方WebSocket,其中请求以一种方法发送,响应以另一种方法给出。如何将这种模式转换为更典型的异步/等待TPL任务,该任务将支持取消(通过令牌)、继续和所有其他功能 这就是我到目前为止提出的,尽管我不确定它是否有效。我要到星期一才能测试 下面是我的问题: 这样行吗 我一直在读关于TaskCompletionSource。有没有更好的方法可以通过TaskCompletionSource实现这些功能 我真的不喜欢锁,因为我知道它可能会阻塞很长一段时间,但我不确定如何做得更好,因为

我需要使用第三方WebSocket,其中请求以一种方法发送,响应以另一种方法给出。如何将这种模式转换为更典型的异步/等待TPL任务,该任务将支持取消(通过令牌)、继续和所有其他功能

这就是我到目前为止提出的,尽管我不确定它是否有效。我要到星期一才能测试

下面是我的问题:

  • 这样行吗

  • 我一直在读关于
    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
    甚至不在