C# .Net 4.5杀了我的第三方物流,现在怎么办?

C# .Net 4.5杀了我的第三方物流,现在怎么办?,c#,task-parallel-library,.net-4.5,C#,Task Parallel Library,.net 4.5,图表1:一些代码将异步(非Async!)网络调用包装到任务中 public static Task<byte[]> GetAsync(IConnection connection, uint id) { ReadDataJob jobRDO = new ReadDataJob(); //No overload of FromAsync takes 4 extra parameters, so we have to wrap // Begin in a Fun

图表1:一些代码将异步(非
Async
!)网络调用包装到
任务中

public static Task<byte[]> GetAsync(IConnection connection, uint id)
{
    ReadDataJob jobRDO = new ReadDataJob();

    //No overload of FromAsync takes 4 extra parameters, so we have to wrap
    // Begin in a Func so that it looks like it takes no parameters except 
    // callback and state
    Func<AsyncCallback, object, IAsyncResult> wrapped = (callback, state) =>
                jobRDO.Begin(connection, 0, 0, id, callback, state);

    return Task<byte[]>.Factory.FromAsync(wrapped, ar =>
    {
        ErrorCode errorCode;
        UInt32 sError;
        UInt32 attribute;
        byte[] data = new byte[10];
        jobRDO.End(out errorCode, out sError, out attribute, out data);
        if(error != ErrorCode.NO_ERROR)  throw new Exception(error.ToString());
        return data;
    }, jobRDO);
}
公共静态任务GetAsync(IConnection连接,uint id) { ReadDataJobRDO=新的ReadDataJob(); //FromAsync的重载不需要额外的4个参数,因此我们必须包装 //在Func中开始,使其看起来不带任何参数,除了 //回调和状态 Func wrapped=(回调,状态)=> 开始(连接,0,0,id,回调,状态); 返回Task.Factory.fromsync(包装,ar=> { 错误代码错误代码; UInt32 sError; UInt32属性; 字节[]数据=新字节[10]; 结束(输出错误代码、输出错误、输出属性、输出数据); if(error!=ErrorCode.NO_error)抛出新异常(error.ToString()); 返回数据; },jobRDO); }
安装.NET4.5(不指向它,也不重新编译)会停止此工作。永远不会调用回调


你知道是什么原因造成的吗?或者,我能做些什么来进一步缩小问题的根本原因或者解决问题?

重新编辑:我已经与你交换了几封电子邮件。下面我试图将我的原始答案和他的答案合并成一个连贯的整体

tl;dr要解决此问题,请强制
同步完成
始终返回false(警告非选择器)


.Net 4.5“破坏性”更改的MSDN文档 发布此问题后,我立即点击a,最后点击,这是关于
fromsync

更改
IAsyncResult
实现必须同步完成,其
CompletedSynchronously
属性必须返回true 用于完成生成的任务

影响:如果
IAsyncResult
实现未完成同步执行,但其
CompletedSynchronously
属性返回True

具有讽刺意味的是(或令人愤怒的是),美国的这一页:

实现者注意事项:IAsyncResult接口的大多数实现者不会使用此属性,应返回false


Stephen Toub对此进行了以下澄清: 桌子在 , 特别是对“变化”的描述是错误的(…)

在.NET4.5中,从Async更改为
,但并非如此
IAsyncResult.CompletedSynchronously
实现必须返回true: 那没有任何意义。实际上,更改是
fromsync
现在查看
IAsyncResult的CompletedSynchronously
(它没有查看 在.NET4)中,它根本就不需要,因此它希望它是准确的。作为 这样,如果您有一个bug
IAsyncResult
实现,
fromsync
可能 仍然在.NET4中工作,而在.NET4.5中,这种可能性较小 使用错误的实现

具体来说,如果
IAsyncResult.CompletedSynchronously
返回
false
。但是,如果返回
true
,则
IAsyncResult
必须在 事实同步完成。如果
同步完成
返回
true
但是
IAsyncResult
尚未完成,您有一个需要 要修复,很可能是从
fromsync
将无法正确完成

出于性能原因进行了更改


回到我的问题代码 下面是他非常有用的分析,我将其全部包括在内,因为它可能对
IAsyncResult
的其他实现者有用:

问题似乎是您正在使用的库有一个非常复杂的问题
IAsyncResult
的错误实现;特别是 同步完成的
实现不正确。这是他们的
实施:

public bool CompletedSynchronously
{
    get { return _isCompleted; }
}
public bool IsCompleted
{
    get { return _isCompleted; }
}
\u isCompleted
字段指示异步操作是否已完成 已经完成,这很好,可以从
已完成
,因为该属性用于指示 操作是否已完成。但是同步完成的
不能
返回同一字段:
CompletedSynchronously
需要返回 操作同步完成,即是否完成 在调用
BeginXx
期间,它必须始终返回相同的值 对于给定的
IAsyncResult
实例

考虑一下如何使用的标准模式 使用
IAsyncResult.CompletedSynchronously
。其目的是允许
BeginXx
的调用方继续执行后续工作,而不是 而不是在工作结束后进行回调。这一点尤其重要 为了避免堆栈跳水(想象一个长序列的异步 所有实际同步完成的操作:如果 处理所有的工作,然后每个回调将启动下一个回调 操作,其回调将启动下一个操作,但 因为它们是同步完成的,所以它们的回调也会 可以作为
BeginXx
方法的一部分同步调用,因此每次调用 会在堆栈上越来越深,直到 溢出):

请注意,调用方和回调都使用相同的
CompletedSynchronously
属性,以确定其中哪个运行 回拨。因此,
CompletedSynchronously
必须始终返回相同的值 此特定实例的值。如果没有,那就是错误的行为 这很容易产生结果。例如,它们的实施已经完成
同步完成
返回
IAsyncResult ar = BeginXx(…, delegate(IAsyncResult iar) =>
{
    if (iar.CompletedSynchronously) return;
    … // do the completion work, like calling EndXx and using its result
}, …);
if (ar.CompletedSynchronously)
{
    … // do the completion work, like calling EndXx and using its result
}