Task.Factory.fromsync在Xamarin.iOS中调用C#base方法时出现错误
我正在使用最新版本的Task.Factory.fromsync在Xamarin.iOS中调用C#base方法时出现错误,c#,ios,xamarin.ios,async-await,C#,Ios,Xamarin.ios,Async Await,我正在使用最新版本的Xamarin.iOS(8.10.5.26)。在开发大量使用async/await方法的跨平台库时,我发现它在Android、Mono和Microsoft CLR上运行良好,但在iOS上崩溃。缩小问题的范围导致了我怀疑在iOS上CLR实现中的一个bug 如果您有一个从NetworkStream派生的类MyNetworkStream,该类重写了它的方法,当调用者假定应该调用base.EndRead时,iOS版本可以调用MyNetworkStream的EndRead。在这种情况下
Xamarin.iOS
(8.10.5.26)。在开发大量使用async/await方法的跨平台库时,我发现它在Android、Mono和Microsoft CLR上运行良好,但在iOS上崩溃。缩小问题的范围导致了我怀疑在iOS上CLR实现中的一个bug
如果您有一个从NetworkStream
派生的类MyNetworkStream
,该类重写了它的方法,当调用者假定应该调用base.EndRead
时,iOS版本可以调用MyNetworkStream的
EndRead
。在这种情况下会发生这种情况:
int bytesRead = await Task.Factory.FromAsync<int>(base.BeginRead(buffer, 0, count, null, null), base.EndRead);
iOS版本会导致
invalidooperationexception
出现“EndRead ERROR”消息,其他版本则不会,因为它们从未进入MyNetworkStream.EndRead
(或任何MyNetworkStream
方法)。有趣的是,base.BeginRead
是可以的,只有base.EndRead
是个问题。例如,Task.Factory.fromsync
为Begin方法选择正确的值,但不为End对应项选择正确的值(因为第一个值只是IAsyncResult
,而第二个值是Func)。因此,我想问题在于Func。非常简单的解决方法似乎是这样的:'Func f=base.EndRead;int bytesRead=wait Task.Factory.fromsync(base.BeginRead(buffer,0,count,null,null),f);”。这很有效。但是,为什么原始表单不起作用的问题仍然存在。我认为您应该提交一份bug报告。非常简单的解决方法似乎是这样的:'Func f=base.EndRead;int bytesRead=wait Task.Factory.fromsync(base.BeginRead(buffer,0,count,null,null),f);”。这很有效。然而,为什么原始表单不起作用的问题仍然存在。我认为你应该提交一份bug报告
public class MyNetworkStream : NetworkStream
{
public MyNetworkStream(Socket sock) : base(sock)
{
}
public override IAsyncResult BeginRead(byte[] buffer, int offset, int size, AsyncCallback callback, object state)
{
throw new InvalidOperationException("BeginRead ERROR");
return base.BeginRead(buffer, offset, size, callback, state);
}
public override int EndRead(IAsyncResult asyncResult)
{
int x = 0;
throw new InvalidOperationException("EndRead ERROR");
return base.EndRead(asyncResult);
}
public override int Read(byte[] buffer, int offset, int count)
{
throw new InvalidOperationException("Read ERROR");
return base.Read(buffer, offset, count);
}
public override async Task<int> ReadAsync(byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken)
{
int bytesRead = await Task.Factory.FromAsync<int>(base.BeginRead(buffer, 0, count, null, null), base.EndRead);
return bytesRead;
}
}
// Put this in a button click handler or something like that.
using (TcpClient client = new TcpClient("mail.afterlogic.com", 143))
{
MyNetworkStream mns = new MyNetworkStream(client.Client);
byte[] b = new byte[1024];
await mns.ReadAsync(b, 0, b.Length);
}