关于 AsyncCallback 和 IAsyncResult 的回调模式的两个问题。
我用代码示例更改了问题:
using System;
using System.Collections.Generic;
using System.Text;
namespace TestAsync
{
class Program
{
private static Wrapper test = new Wrapper();
static void Main(string[] args)
{
test.BeginMethod("parameter 1", "parameter 2", Callback);
Console.ReadKey();
}
private static void Callback(IAsyncResult ar)
{
string result = test.EndMethod(ar);
}
}
public interface ITest
{
IAsyncResult BeginMethod(string s1, string s2, AsyncCallback cb, object state);
string EndMethod(IAsyncResult result);
}
public class Wrapper
{
private ITest proxy = new Test();
public void BeginMethod(string s1, string s2, AsyncCallback cb)
{
proxy.BeginMethod(s1, s2, cb, proxy);
}
public string EndMethod(IAsyncResult result)
{
return ((ITest)(result.AsyncState)).EndMethod(result);
}
}
public class Test : ITest
{
private string WorkerFunction(string a, string b)
{
// "long running work"
return a + "|" + b;
}
public IAsyncResult BeginMethod(string s1, string s2, AsyncCallback cb, object state)
{
Func<string, string, string> function = new Func<string, string, string>(WorkerFunction);
IAsyncResult result = function.BeginInvoke(s1, s2, cb, state);
return result;
}
public string EndMethod(IAsyncResult result)
{
return (string)(result.AsyncState);
}
}
public delegate TResult Func<T1, T2, TResult>(T1 t1, T2 t2);
}
开始编辑
我开始明白发生了什么。
我混淆了 WCF 异步模式和普通异步模式。
在 WCF 中,使用代理并且 Begin- 和 EndMethod 必须通过代理而不是函数委托(delegate)。在 WCF 情况下,转换有效,在正常情况下则无效。
WCF 使用 [OperationContract(AsyncPattern = true)] 属性可能会强制实现一种稍微不同的模式。
结束编辑
为什么 return (string)(result.AsyncState); 行会出错?
生产代码中完全相同的模式是可以的。
其次,为什么不能调试Test类的BeginMethod中的代码?
我只能在 WorkerFunction 中打断。
最佳答案
让我给你这个示例代码,让事情变得更清楚。请创建一个新的控制台应用程序并使用它
public class Test
{
private int WorkerFunction(string a, string b)
{
//this is the guy that is supposed to do the long running work
Console.WriteLine(a);
Console.WriteLine(b);
return a.Length + b.Length;
}
private void MyCallBack(IAsyncResult ar)
{
Func<string, string, int> function = ar.AsyncState as Func<string, string, int>;
int result = function.EndInvoke(ar);
Console.WriteLine("Result is {0}", result);
}
public void CallMethod()
{
Func<string, string, int> function = new Func<string, string, int>(WorkerFunction);
IAsyncResult result = function.BeginInvoke("param1", "param2", MyCallBack, function);
}
}
class Program
{
static void Main(string[] args)
{
Test test = new Test();
test.CallMethod();
}
}
如您所见,回调函数 (MyCallBack) 获取传回给它的 IAsyncResult 对象。正是这个 IAsynchResult 对象的 AyncState 为您提供了您在 BeginInvoke 方法调用中传递的原始对象。在这种情况下(并且作为一般做法),您将委托(delegate)本身作为对象(这是称为“函数”的变量)传递。 回调被调用后,我通过查询 ar.AsyncState 取回了原始委托(delegate)对象,然后调用了 EndInvoke 以取回结果。
至于断点没有被击中,恐怕我需要更多的信息。你到底什么意思?这个 Console.WriteLine 语句在哪里?
新回应 好的,这是我的代码版本。基本上,无论您从何处调用 EndInvoke,都需要在实际的委托(delegate)对象上调用它(在您的例子中是您实例化的“函数”变量,将其传递给实际的 IAsyncResult 对象)。您拥有的代码试图掩盖此功能,但是我必须说,执行此操作的方法不那么复杂。如果您愿意,我将非常乐意为您编写各种 wrapper 。现在,我只是将您的代码返回给您,并在其中添加了少量内容,这应该可以使它正常工作。由于您使用的是类级别变量,因此我不得不自己使用一个。目前这并不是真正的线程安全。但是这里是
using System;
using System.Collections.Generic;
using System.Text;
namespace TestAsync
{
class Program
{
private static Wrapper test = new Wrapper();
static void Main(string[] args)
{
var objectState = new object();
test.BeginMethod("parameter 1", "parameter 2", Callback, objectState);
Console.ReadKey();
}
private static void Callback(IAsyncResult ar)
{
string result = test.EndMethod(ar);
Console.WriteLine(result);
}
}
public interface ITest
{
IAsyncResult BeginMethod(string s1, string s2, AsyncCallback cb, object state);
string EndMethod(IAsyncResult result);
}
public class Wrapper
{
private ITest proxy = new Test();
public void BeginMethod(string s1, string s2, AsyncCallback cb)
{
proxy.BeginMethod(s1, s2, cb, proxy);
}
public string EndMethod(IAsyncResult result)
{
return ((ITest)(result.AsyncState)).EndMethod(result);
}
}
public class Test : ITest
{
Func<string, string, string> _delgateObject;
private string WorkerFunction(string a, string b)
{
// "long running work"
return a + "|" + b;
}
public IAsyncResult BeginMethod(string s1, string s2, AsyncCallback cb, object state)
{
Func<string, string, string> function = new Func<string, string, string>(WorkerFunction);
this._delgateObject = function;
IAsyncResult result = function.BeginInvoke(s1, s2, cb, state);
return result;
}
public string EndMethod(IAsyncResult result)
{
var test = result.AsyncState;
return this._delgateObject.EndInvoke(result);
}
}
public delegate TResult Func<T1, T2, TResult>(T1 t1, T2 t2);
}
关于c# - 关于 AsyncCallback 和 IAsyncResult 模式的两个问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5089095/
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende
我的最终目标是安装当前版本的RubyonRails。我在OSXMountainLion上运行。到目前为止,这是我的过程:已安装的RVM$\curl-Lhttps://get.rvm.io|bash-sstable检查已知(我假设已批准)安装$rvmlistknown我看到当前的稳定版本可用[ruby-]2.0.0[-p247]输入命令安装$rvminstall2.0.0-p247注意:我也试过这些安装命令$rvminstallruby-2.0.0-p247$rvminstallruby=2.0.0-p247我很快就无处可去了。结果:$rvminstall2.0.0-p247Search
由于fast-stemmer的问题,我很难安装我想要的任何rubygem。我把我得到的错误放在下面。Buildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingfast-stemmer:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcreatingMakefilemake"DESTDIR="cleanmake"DESTDIR=
当我尝试安装Ruby时遇到此错误。我试过查看this和this但无济于事➜~brewinstallrubyWarning:YouareusingOSX10.12.Wedonotprovidesupportforthispre-releaseversion.Youmayencounterbuildfailuresorotherbreakages.Pleasecreatepull-requestsinsteadoffilingissues.==>Installingdependenciesforruby:readline,libyaml,makedepend==>Installingrub
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL