从MS had said that both APM and EAP are outdated开始,TAP是.NET Framework中异步编程的推荐方法。然后我想将我的代码从APM转换为TAP:
public class RpcHelper
{
public void DoReadViaApm(IRpc rpc, BlockingCollection<ArraySegment<byte>> bc)
{
byte[] buf = new byte[4096];
rpc.BeginRead(buf, 0, buf.Length,
ar =>
{
IRpc state = (IRpc) ar.AsyncState;
try
{
int nb = state.EndRead(ar);
if (nb > 0)
{
bc.Add(new ArraySegment<byte>(buf, 0, nb));
}
}
catch (Exception ignored)
{
}
finally
{
DoReadViaApm(state, bc);
}
},
rpc);
}
public void DoReadViaTap(IRpc rpc, BlockingCollection<ArraySegment<byte>> bc)
{
Task.Factory.StartNew(() =>
{
while (true)
{
Task<byte[]> task = rpc.ReadAsync();
try
{
task.Wait(-1);
if (task.Result != null && task.Result.Length > 0)
{
bc.Add(new ArraySegment<byte>(task.Result));
}
}
catch (Exception ignored)
{
}
}
}, TaskCreationOptions.LongRunning);
}
}
public interface IRpc
{
IAsyncResult BeginRead(byte[] buffer, int offset, int size, AsyncCallback callback, Object state);
int EndRead(IAsyncResult asyncResult);
Task<byte[]> ReadAsync();
}
TAP方法DoReadViaTap()使用TaskCreationOptions.LongRunning,它看起来非常难看。我可以让DoReadViaTap()看起来更像DoReadViaApm()吗?
答案 0 :(得分:0)
我不完全确定你的代码应该做什么,但我想这是一些等待输入的工人?
您可以使用await
来简化它,并使启动的操作异步。请注意,任务有超时,因此您可能需要适当地设置或捕获异常。
public void DoReadViaTap(IRpc rpc, BlockingCollection<ArraySegment<byte>> bc)
{
Task.Factory.StartNew(async () =>
{
while (true)
{
byte[] result = await rpc.ReadAsync();
if (result.Length > 0)
{
bc.Add(new ArraySegment<byte>(result));
}
catch (AggregateException ignored)
{
}
}
}, TaskCreationOptions.LongRunning);
}
答案 1 :(得分:0)
您应该使用async
- await
。当你这样做时,你不需要开始Task
:
public async Task DoReadViaTap(IRpc rpc, BlockingCollection<ArraySegment<byte>> bc)
{
while (true)
{
try
{
byte[] result = await rpc.ReadAsync().ConfigureAwait(false);
if (result != null && result.Length > 0) // or result?.Length > 0 on C# 6
{
bc.Add(new ArraySegment<byte>(result));
}
}
catch (Exception ignored)
{
}
}
}
对我而言,这比APM版本要好得多。
请注意,我不认为完全忽略异常和无限循环而无法结束它们是良好做法,我只是从您的代码中复制了这些。