我有关于异步调用方法的设计问题。
我想知道调用异步方法的最佳/好模式,它调用另一个异步方法,它调用另一个异步方法:)
换句话说,我使用异步方法创建了WCF服务引用,并希望从其他异步方法调用它们。所有这些都是为了非阻塞GUI。
谢谢!
发布于 2010-06-10 15:18:22
如果您唯一的目标是拥有一个非阻塞的GUI,那么多个级别是不必要的。一旦toplevel方法在后台运行,您的GUI就被释放了。使用多个级别确实会带来额外的复杂性。
可能还有其他原因(性能)来调用较低级别的异步方法,但这取决于。你需要等待稍后的结果吗?
所以我不认为这里有一个‘模式’。
发布于 2010-09-14 15:55:39
在像MonoRail或MVC这样的MVC框架中创建异步控制器时,就是拥有多个级别的一个好例子。最终调用IO阻塞的东西,例如来自System.Data.SqlClient或某个套接字的SqlCommand,会将IO操作数放在IO完成端口上:http://msdn.microsoft.com/library/aa365198,这将节省托管/非托管线程的量程,以便做更有用的事情。
如果您编写返回IAsyncResult的类,那么就离实现协同例程不远了。这里有一篇关于如何将异步编程与协程结合使用的好文章:http://blogs.msdn.com/b/pfxteam/archive/2009/06/30/9809774.aspx。
Caliburn是一个WPF框架,它本身就支持协同例程。与.Net 4一起发布的任务并行库为其任务提供了IAsyncResult接口。如果你的版本是3.5,那么你可能需要创建自己的实现(它们很容易实现,只需实现接口即可)。协同例程是一种使用编译器重写IEnumerable来将IAsyncResults推送到一堆要做的事情的方式(从“异步管理器”中可以看到)。
CLR(就像在向下投票的答案中看到的那样)使用monad (就像它们在F#上获得的那样)来将异步请求的状态从Begin*移动到End*方法。编译器将其编译成嵌套的lambda表达式/SelectMany。
发布于 2016-01-13 00:32:26
我最近开发了ADFS属性存储的实现,它调用后端web服务来检索数据。我想遵循工厂->客户端的方法,而不是对每个调用重用客户端,所以我最终使用了2级异步调用,如下面的简化代码示例所示:
public class IMyAttributeStore : IAttributeStore
{
ChannelFactory<IMyBackendInterface> factory;
public IMyAttributeStore()
{
}
public IAsyncResult BeginExecuteQuery(string query, string[] parameters, AsyncCallback callback, object state)
{
AsyncResult queryResult = new TypedAsyncResult<string[][]>(callback, state);
var client = factory.CreateChannel();
CallState cs = new CallState(client, queryResult);
Request rq = new Request();
client.BeginGetUserRoles(rq, new AsyncCallback(AsyncCallCallback), cs);
return cs.result;
}
public string[][] EndExecuteQuery(IAsyncResult result)
{
return TypedAsyncResult<string[][]>.End(result);
}
// Initialize state here.
public void Initialize(Dictionary<string, string> config)
{
var endpoint = config["endpointConfigurationName"];
factory = new ChannelFactory<IMyBackendInterface>(endpoint);
}
void AsyncCallCallback(IAsyncResult result)
{
CallState cs = (CallState)result.AsyncState;
Response data = cs.client.EndGetUserRoles(result);
List<string[]> claimData = new List<string[]>();
foreach (var val in data.Values)
claimData.Add(new string[1] { val });
string[][] retVal = claimData.ToArray();
TypedAsyncResult<string[][]> queryResult = (TypedAsyncResult<string[][]>)cs.result;
queryResult.Complete(retVal, false);
}
}
class CallState
{
public IMyBackendInterface client;
public AsyncResult result;
public CallState(IMyBackendInterface c, AsyncResult r)
{
client = c;
result = r;
}
}想知道这是一个很好的模式,还是有人同时发现了更好的模式?
https://stackoverflow.com/questions/3012319
复制相似问题