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);
}