public virtual async Task<Packet> SendAndWaitResponse(Packet packet, ushort responsePacketId, Func<Packet, bool> predicate, int timeout)
{
TaskCompletionSource<Packet> tcs = new TaskCompletionSource<Packet>();
CancellationTokenSource cancel = new CancellationTokenSource();
TCSData data = new TCSData() { packetId = responsePacketId, tcs = tcs, predicate = predicate };
Packet response = null;
lock (_listTCS)
{
_listTCS.Add(data);
}
// Task.Result의 Timeout 처리
Task.Run(async () =>
{
try
{
await Task.Delay(timeout, cancel.Token);
tcs.SetCanceled();
}
catch (Exception)
{
}
});
// Packet Send & Response 작업
await Task.Run(() =>
{
try
{
_session.SendPacket(packet);
response = tcs.Task.Result;
cancel.Cancel();
}
catch (Exception)
{
// Task가 Cancel된 경우 추가된 작업(data)을 삭제한다.
_listTCS.Remove(data);
}
});
cancel.Dispose();
if (response == null)
throw new WaitResponseTimeoutException("The waiting time of ResponsePacketId(0x{0:X}) has expired.", responsePacketId);
return response;
}
}