I've got an async discover function which discovers devices in the local network which I call on a button click. I'm sending a broadcast message to all devices and listen for responses for 5 seconds using a CancellationTokenSource
. After the token has expired I'm returning an IEnumerable
of parsed responses to my WPF model.
I'd like return incoming responses directly (and stop listening after 5 seconds) so that I can show discovered devices instantly in the UI instead of showing them all after 5 seconds.
This is my code:
public async Task<IEnumerable<IDevice>> Discover()
{
var client = new MyClient();
var responseData = await GetResponseData(client);
return this.ParseResponseData(responseData);
}
private IEnumerable<IDevice> ParseResponseData(List<DeviceResponseData> responseData)
{
foreach (var data in responseData)
{
yield return DeviceFactory.Create(data);
}
}
private static async Task<List<DeviceResponseData>> GetResponseData(MyClient client,
int timeout = 5000)
{
var cancellationToken = new CancellationTokenSource(timeout);
var data = new List<DeviceResponseData>();
// ... prepare message and send it
await client.SendAsync(message, new CancellationToken());
try
{
while (!cancellationToken.IsCancellationRequested)
{
// Wait indefinitely until any message is received.
var response = await client.ReceiveAsync(cancellationToken.Token);
data.Add(new DeviceResponseData(/* ... */ response));
}
}
catch (TaskCanceledException e)
{
}
return data;
}