我在做C#项目。我想通过websocketsharp库以某种同步的方式发送API请求。
我一直试着按照以下方式去做:
>
在发送任何WS请求之前,我们使用唯一的ID创建新的SynchronousRequest()对象,并将新创建的对象添加到某种类型的等待列表中
我们在响应中发送WS请求,向有效负载添加唯一的ID-服务器将返回相同的ID。
我们开始等待事件发出信号(一旦我们收到响应就会发出信号)
在响应处理程序上:
问题是第3步,一旦我在事件上使用WaitOne(),整个websocket客户机就挂起了,并且不会收到进一步的响应--导致完全死锁。
我如何在单独的线程中执行某种WaitOne()调用,或者可能有完全更好的解决方案来解决我的问题,从而使整个客户端不会挂起,并且我们匹配上下文?
public class SynchronousRequest
{
public long requestId;
public ManualResetEvent resetEvent = new ManualResetEvent(false);
public dynamic response;
public SynchronousRequest()
{
var random = new Random();
requestId = random.Next();
}
}
public class APIWebSocket: BaseAPIWebSocket
{
private List<SynchronousRequest> waitingSyncRequests = new List<SynchronousRequest>();
public APIWebSocket()
{
ws = new WebSocket("wss://www.someserver.com");
registerConnectionEvents(); //Registers onOpen(), onMessage() handlers and similar
}
public void SendSyncTest()
{
var sr = new SynchronousRequest();
waitingSyncRequests.Add(sr);
//some data to send
var msg = new
{
jsonrpc = "2.0",
method = "public/ticker",
id = sr.requestId, //Response should contain the same ID
@params = new
{
instrument_name = "ETH"
}
};
ws.Send(JsonConvert.SerializeObject(msg));
//Below WaitOne() causes the entire websocket connection/thread to block
// No further messages will be received by HandleMessage() once we call WaitOne()
sr.resetEvent.WaitOne(); //Wait until we receive notification that response has been received
//do some processing on response here...
//Synchronous request completed, remove it from list
waitingSyncRequests.Remove(sr);
}
protected override void OnReceivedMessage(System.Object sender, WebSocketSharp.MessageEventArgs e)
{
dynamic message = JsonConvert.DeserializeObject(e.Data);
if (message.id != null )
{
//Find a resetEvent for given message.id
var matchingSyncRequest = waitingSyncRequests.First(r => r.requestId == message.id);
if (matchingSyncRequest != null)
{
matchingSyncRequest.response = message;
matchingSyncRequest.resetEvent.Set(); //Notify that response has been received
}
}
}
}
根据我的理解,对于将在将来某个时间设置的某个事件,您需要await
。您可以考虑使用TaskCompletionSource
。
>
1.每当您发送需要其结果的消息时,您可以创建TaskCompletionSource
(tcs),将其添加到Dictionary
并通过套接字发送消息。
2.您在TCS
上等待tcs.task
或tcs.task.result
。
3.在另一个线程
/任务
上,您可以处理传入的响应
(在您的情况下,您有您的received message Handler。每当您接收到目标类型
或id
的响应时,您可以根据id从字典中提取TCS
和Task.setResult(response)
。这时,调用方(您正在等待的调用方)将被解除阻止。
public class Message
{
public string ID{get;set;}
}
public class Response
{
public string Id{get;set;}
}
public void MyClass
{
private ConcurrentDictionary<string,TaskCompletionSource<Response>>map=new ConcurrentDictionary<string,TaskCompletionSource<Response>>();
private Websocket socket;
public void SomeEventTrigger()
{
var msg=new Message{ Id="somespecialID" };
var tcs=new TaskCompletionSource<Response>();
ws.Send(JsonConvert.SerializeObject(msg));
if(!this.map.TryAdd(msg.Id,tcs))
{
return;
}
var result=tcs.Result; //this gets blocked until you use `tcs.SetResult`- > that would happen in your OnReceivedMessage
this.map.TryRemove(msg.Id,out TaskCompletionSource<Response>resp);
}
protected override void OnReceivedMessage(System.Object sender, WebSocketSharp.MessageEventArgs e)
{
Response message = JsonConvert.DeserializeObject<Response>(e.Data);
if (message.id != null )
{
if(this.map.TryGetValue(message.id),out TaskCompletionSource<Response> tcs)
{
tcs.SetResult(message); //this unblocks the method that wrote the message to the socket (above)
}
}
}
}
p.s您需要确保在正确的TCS
上使用Task.SetResult
,以便对SomeEventTrigger
方法的正确调用停止等待。
问题内容: 我正在尝试使用进行同步请求。我查看了Stackoverflow并发现了这个问题:使异步alamofire请求成为sync 我看到接受的答案用于使请求同步,但是我无法使其正常工作。这是我的简化代码: 有了这段代码,我在尝试制作时会出错。我收到的错误如下: 无法调用非功能类型“布尔”的值 我尝试使用许多使用完成的示例来同步获取值(因为我需要先检索数据才能将其显示在表上,并同时获取该表的行数
Spring留档声明,即使要执行同步超文本传输协议调用,我们也必须从RestTemboard切换到。 目前,我有以下代码: 当然,我可以在这里使用CountdownLatch,但它看起来像是API滥用。 如何执行同步请求?
问题内容: 如何使Ajax请求同步? 我有一个需要提交的表格。但是只有在用户输入正确的密码时才需要提交。 这是表单代码: 用于发送和检查密码的jQuery代码是这样的: 但是,无论ajax请求返回的值如何,该表单始终提交。我检查了其他所有内容。输入正确的密码后,arr的值将显示为“成功”,反之亦然。 如何使此请求同步?据我可以调试,请求是异步的,因此在请求完成之前先提交表单。 checkpass.
问题内容: 我读了一些将jsons发布到服务器的示例。 有人说: OkHttp是Java提供的HttpUrlConnection接口的实现。它提供用于编写内容的输入流,并且不知道(或不在乎)内容的格式。 现在,我想用名称和密码的参数对URL进行常规发布。 这意味着我需要自己将名称和值对编码为流? 问题答案: 当前接受的答案已过期。现在,如果您想创建一个发布请求并向其中添加参数,则应该使用Mul
我阅读了一些将jsons发布到服务器的示例。 有人说: OkHttp是Java提供的HttpUrlConnection接口的实现。它提供了一个用于写入内容的输入流,而不知道(或关心)该内容是什么格式。 现在我想用name和password参数对URL做一个普通的post。 这意味着我需要自己将名称和值对编码成流?
本文向大家介绍vue如何使用async、await实现同步请求,包括了vue如何使用async、await实现同步请求的使用技巧和注意事项,需要的朋友参考一下 这篇文章主要介绍了vue如何使用async、await实现同步请求,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 以下是vue method的demo: 其中方法需要用async修饰, 然