public async TaskStartDownloadRequestAsync (StartDownloadMsg MSG, int requestCount, TimeSpan interval)
{
Var data=https://bbs.csdn.net/topics/MessageConverter.Serialize (MSG);
Var response=await the Request (MSG) Header) MessageType, data, requestCount, interval);
Return MessageConverter. Deserialize(response);
}
Request:
private async Task{
ValidRequest (type);
_cts=new CancellationTokenSource ();
Try
{
For (int count=0; The count & lt; RequestCount; Count++)
{
Send (MSG);
Await Task. Delay (interval, _cts Token);
}
}
The catch (OperationCanceledException)
{
TaskCompletionSourceTask. SetResult (_response);
Return await task. A task;
}
The finally
{
_isRequesting=false;
_response=null;
}
Throw new RequestTimeoutException ();
}
Receive a callback:
private void ReceiveCallback (IAsyncResult async)
{
The Socket Socket=async. AsyncState as Socket;
Int length=socket. EndReceive (async);
_buffer. Write (_received, 0, length);
_buffer. Seek (- length, SeekOrigin. End);
While (_buffer) Length - _buffer) Position & gt;=CanFrameLength)
{
Byte [] package=new byte [CanFrameLength];
_buffer. Read (package, 0, CanFrameLength);
Var type=(MessageType) package [TypeOffset];
The switch (type)
{
Case MessageType. StartDownloadResponse:
Case MessageType. DemandSectionResponseTwo:
Case MessageType.Com binePackageResponse:
Case MessageType.Com binePackageCompletedResponse:
Case MessageType. ProgramCheckoutResponse:
Case MessageType. ResetImmeiateResponse:
If (_isRequesting & amp; & Type==_waitResponseType)//is asking and the type of message types for response to
{
_response=package;
_cts. Cancel ();//direct request task
}
break;
Case MessageType. HeartbeatResponse:
_lastHeartbeat + +;
break;
Default:
break;
}
}
Socket. BeginReceive (_received, 0, _received. Length, SocketFlags. None, ReceiveCallback, socket);
}
Another way I can think of is every request to open a timer timing to send request, receive a callback after receive the specified response to stop the timer and inform requestor by events, the timer reaches the specified number haven't stop throwing timeout exception, this approach can not directly in the request function returns responses inside, use rise more troublesome,
As well as use WaitHandle to synchronization, request function inside loop to send to:
for (int count=0; The count & lt; RequestCount; Count++)
{
Send (MSG);
If (resetEvent. WaitOne (interval))
{
Return _response;
}
}
After receiving the specified response resetEvent. Set (), the way back to the threads blocked requests
Don't know if you have more elegant
CodePudding user response:
I also write something similar,I am such processing
The class FunctionRquestData
{
Private Stopwatch sw=new Stopwatch ();
Public class packagedata
{
FunctionRquestData f;
Public Dictionary();
Public void addreceivedata (int n, byte [] d)
{
if (! Data. Either ContainsKey (n))
{
Data. The Add (n, d);
F.f inished=false;
F. heckdone ();
F.s w.R estart ();
}
}
Public void addsenddata (int n, byte [] d)
{
//if (! Data. Either ContainsKey (n))
{
Data. The Add (n, d);
Udp. Send (d, d.L ength, f.i p);
}
}
Public int the count ()
{
Return the data. The Count;
}
Public void the clear ()
{
Data. The Clear ();
}
Public packagedata (FunctionRquestData F)
{
F=f;
}
}
Void checkdone ()
{
//determine whether complete
}
Void checktimeout ()
{
System. The Timers. The Timer dt=new System. Timers. The Timer () {Enabled=true, the Interval=100};
Dt. Elapsed +=delegate
{
if (! Finished)
{
If (sw) ElapsedMilliseconds & gt; 500)
{
Sw. Restart ();
//not finished processing
0.5 seconds}
}
If (sw) ElapsedMilliseconds & gt; 7000)
{
Senddata publishes the event. The clear ();
Dt. The Dispose ();//7 seconds after the delete
}
};
}
Public FunctionRquestData ()
{
Sw. Start ();
Checktimeout ();
}
}
CodePudding user response: