首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >c#中的多级异步方法调用模式

c#中的多级异步方法调用模式
EN

Stack Overflow用户
提问于 2010-06-10 15:07:44
回答 3查看 1.1K关注 0票数 1

我有关于异步调用方法的设计问题。

我想知道调用异步方法的最佳/好模式,它调用另一个异步方法,它调用另一个异步方法:)

换句话说,我使用异步方法创建了WCF服务引用,并希望从其他异步方法调用它们。所有这些都是为了非阻塞GUI。

谢谢!

EN

回答 3

Stack Overflow用户

发布于 2010-06-10 15:18:22

如果您唯一的目标是拥有一个非阻塞的GUI,那么多个级别是不必要的。一旦toplevel方法在后台运行,您的GUI就被释放了。使用多个级别确实会带来额外的复杂性。

可能还有其他原因(性能)来调用较低级别的异步方法,但这取决于。你需要等待稍后的结果吗?

所以我不认为这里有一个‘模式’。

票数 3
EN

Stack Overflow用户

发布于 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。

票数 0
EN

Stack Overflow用户

发布于 2016-01-13 00:32:26

我最近开发了ADFS属性存储的实现,它调用后端web服务来检索数据。我想遵循工厂->客户端的方法,而不是对每个调用重用客户端,所以我最终使用了2级异步调用,如下面的简化代码示例所示:

代码语言:javascript
运行
复制
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;
    }
}

想知道这是一个很好的模式,还是有人同时发现了更好的模式?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3012319

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档