Если ваш интерфейс требует, чтобы вы вернули задачу, вы можете закончить ненужное планирование работы в пуле потоков, просто чтобы выполнить вызов BeginSend () (это то, что происходит в предыдущем ответе, где вызов FromAsync () упакован другим заданием).
Вместо этого, если вы можете изменить интерфейс, вы можете использовать стандартную технику отложенного выполнения, такую как:
public static Func<Task<int>> SendAsync(this Socket socket, byte[] buffer, int offset, int count)
{
if (socket == null) throw new ArgumentNullException("socket");
if (buffer == null) throw new ArgumentNullException("buffer");
return () =>
Task.Factory.FromAsync<int>(
socket.BeginSend(buffer, offset, count, SocketFlags.None, null, socket),
socket.EndSend);
}
Вызывающая сторона будет вызывать результат для запуска операции (то есть вызова FromAsync / BeginSend) и использовать ContinueWith () для обработки результата:
Func<Task<int>> sendAsync = socket.SendAsync(buffer, offset, count);
sendAsync().ContinueWith(
antecedent => Console.WriteLine("Sent " + antecedent.Result + " bytes."));
Если использование Func <> в вашем интерфейсе не подходит, вы можете заключить его в отдельный класс:
public class DelayedTask<TResult>
{
private readonly Func<Task<TResult>> func;
public DelayedTask(Func<Task<TResult>> func)
{
this.func = func;
}
public Task<TResult> Start()
{
return this.func();
}
}
public static DelayedTask<int> SendAsync(this Socket socket, byte[] buffer, int offset, int count)
{
if (socket == null) throw new ArgumentNullException("socket");
if (buffer == null) throw new ArgumentNullException("buffer");
return new DelayedTask<int>(() =>
Task.Factory.FromAsync<int>(
socket.BeginSend(buffer, offset, count, SocketFlags.None, null, socket),
socket.EndSend));
}
И вызывающий абонент будет выглядеть так:
DelayedTask<int> task = socket.SendAsync(buffer, offset, count);
task.Start().ContinueWith(
antecedent => Console.WriteLine("Sent " + antecedent.Result + " bytes."));