C# .Net 4.5杀了我的第三方物流,现在怎么办?
图表1:一些代码将异步(非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
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)中,它根本就不需要,因此它希望它是准确的。作为
这样,如果您有一个bugIAsyncResult
实现,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
}