图表 1:将异步(不是 async!)网络调用包装到 Task 中的一些代码
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);
}
安装 .Net 4.5(不指向 VS,也不重新编译)会停止此工作。永远不会调用回调。
知道是什么原因造成的吗?否则,我可以做些什么来尝试进一步缩小问题的根本原因或解决问题?
最佳答案
重新编辑:我与Stephen Toub交换了几封电子邮件。 .下面我尝试将我的原始答案和他的答案合并成一个连贯的整体。
tl;dr 要解决此问题,请强制 CompleteSynchronously 始终返回 false(注意非 lector)。
发布这个问题后,我立即点击了 related question , 并结束于 "Application Compatibility in the .NET Framework 4.5" ,其中有关于 FromAsync 的说法:
Change: The
IAsyncResultimplementation must complete synchronously and itsCompletedSynchronouslyproperty must return true for the resulting task to complete.Impact: The resulting task will not complete if an
IAsyncResultimplementation does not complete synchronous execution but itsCompletedSynchronouslyproperty returns True.
具有讽刺意味的是,(或令人气愤的是)CompletedSynchronously 的页面状态:
Notes to Implementers: Most implementers of the
IAsyncResultinterface will not use this property and should return false.
The table at http://msdn.microsoft.com/en-us/library/hh367887%28v=VS.110%29.aspx#core, and specifically the description of the “Change”, is wrong (...).
There was a change in .NET 4.5 to
FromAsync, but it wasn’t that allIAsyncResult.CompletedSynchronouslyimplementations must return true: that wouldn’t make any sense. The change was thatFromAsyncactually looks at theIAsyncResult’s CompletedSynchronouslynow (it didn’t look at it at all in .NET 4), and thus it expects it to be accurate. As such, if you had a buggyIAsyncResultimplementation,FromAsyncmight still have worked in .NET 4, whereas with .NET 4.5, it’s less likely to work with a buggy implementation.Specifically, it’s ok if
IAsyncResult.CompletedSynchronouslyreturnsfalse. However, if it returnstrue, theIAsyncResultmust have in fact completed synchronously. IfCompletedSynchronouslyreturnstruebut theIAsyncResulthas not completed, you have a bug that needs to be fixed, and it’s likely that theTaskreturned fromFromAsyncwill not complete correctly.The change was made for performance reasons.
这是他非常有用的分析,我将其完整包含在内,因为它可能对 IAsyncResult 的其他实现者有用:
The problem appears to be that the library you’re using has a very faulty implementation of
IAsyncResult; in particular, it’s implementingCompletedSynchronouslyincorrectly. Here’s their implementation:public bool CompletedSynchronously { get { return _isCompleted; } } public bool IsCompleted { get { return _isCompleted; } }Their
_isCompletedfield indicates whether the asynchronous operation has completed, which is fine, and it’s fine to return this fromIsCompleted, since that property is meant to indicate whether the operation completed or not. ButCompletedSynchronouslycan’t just return that same field:CompletedSynchronouslyneeds to return whether the operation completed synchronously, i.e. whether it completed during the call toBeginXx, and it must always return the same value for a givenIAsyncResultinstance.Consider the standard pattern for how
IAsyncResult.CompletedSynchronouslyis used. Its purpose is to allow the caller ofBeginXxto continue doing the follow-on work, rather than having the callback due the work. This is particularly important for avoiding stack dives (imagine a long sequence of asynchronous operations that all actually completed synchronously: if the callbacks handled all of the work, then each callback would initiate the next operation, whose callback would initiate the next operation, but because they were completing synchronously, their callbacks would also be invoked synchronously as part of theBeginXxmethods, so each call would get deeper and deeper on the stack, until it potentially overflowed):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 }Note that both the caller and the callback use the same
CompletedSynchronouslyproperty to determine which of them runs the callback. As such,CompletedSynchronouslymust always return the same value for this particular instance. If it doesn’t, erroneous behavior can easily result. For example, their implementation hasCompletedSynchronouslyreturning the equivalent ofIsCompleted. So imagine the following sequence of events:
BeginXxis called and initiates the async operationBeginXxreturns to its caller, which checksCompletedSynchronously, which is false, because the operation hasn’t completed yet.- Now the operation completes and the callback is invoked. The callback sees that
CompletedSynchronouslyis true, and so doesn’t do any of the subsequent work, because it assumes the caller did it.- And now no one’s run or will run the callback.
In short, the library has a bug. If you changed
CompletedSynchronouslyto return true, you masked this problem, but you likely caused another: if the caller (in your case,FromAsync) thinks that the operation has already completed, it’ll proceed to immediately call theEndXxmethod, which will block until the async operation has completed, so you’ve turned your asynchronous operations into synchronous ones. Have you tried just always returning false fromCompletedSynchronouslyinstead of always returning true?
关于c# - .Net 4.5 杀死了我的 TPL,现在呢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14889514/
作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代
是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou
我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
我喜欢使用Textile或Markdown为我的项目编写自述文件,但是当我生成RDoc时,自述文件被解释为RDoc并且看起来非常糟糕。有没有办法让RDoc通过RedCloth或BlueCloth而不是它自己的格式化程序运行文件?它可以配置为自动检测文件后缀的格式吗?(例如README.textile通过RedCloth运行,但README.mdown通过BlueCloth运行) 最佳答案 使用YARD直接代替RDoc将允许您包含Textile或Markdown文件,只要它们的文件后缀是合理的。我经常使用类似于以下Rake任务的东西:
rails中是否有任何规定允许站点的所有AJAXPOST请求在没有authenticity_token的情况下通过?我有一个调用Controller方法的JqueryPOSTajax调用,但我没有在其中放置任何真实性代码,但调用成功。我的ApplicationController确实有'request_forgery_protection'并且我已经改变了config.action_controller.consider_all_requests_local在我的environments/development.rb中为false我还搜索了我的代码以确保我没有重载ajaxSend来发送
我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha
我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur
简而言之错误:NOTE:Gem::SourceIndex#add_specisdeprecated,useSpecification.add_spec.Itwillberemovedonorafter2011-11-01.Gem::SourceIndex#add_speccalledfrom/opt/local/lib/ruby/site_ruby/1.8/rubygems/source_index.rb:91./opt/local/lib/ruby/gems/1.8/gems/rails-2.3.8/lib/rails/gem_dependency.rb:275:in`==':und
我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我