希望事件处理程序只运行一次/设计状态机吗?

时间:2010-02-16 02:43:27

标签: c# silverlight user-interface design-patterns

我有两种方法的网络服务:

RetrieveFirstLevelOptions()和RetrieveSecondLevelOptions(int levelOneOption)。

GUI包含两个组合框:FirstLevelOptionsCombo和SecondLevelOptionsCombo。

当我必须向RetrieveFirstLevelOptions()发出请求时,我无法为初始化阶段创建控制流,然后,一旦结果出现,就调用RetrieveSecondLevelOptions(默认levelOneOption = 0)。

问题在于,由于一切都是异步发生的,我不知道最好的方法是允许这种行为在开始时只发生一次。

我希望有一个选项是将第二个事件处理程序附加到RetieveFirstLevelOptionsCompleted事件,并在仅运行一次后将其自行删除。但看起来这样的行为是不可能的。

另一种选择是使用布尔标志来指示是否在初始化阶段,如果是,则RetrieveFirstLevelOptionsCompleted的处理程序将执行一些额外的逻辑。然而,这个想法使得所有事件处理程序看起来都必须检查状态信息并根据当前状态执行不同的操作。这似乎是糟糕的设计,因为控制流似乎是分散的。

我想拥有一个集中控制流程机制,可以在一个地方做出决定。但是当一切都是异步执行时,如何才能做到这一点?

2 个答案:

答案 0 :(得分:1)

我通常在这种情况下使用的模式是围绕接受回调方法的Async Web服务代理方法创建一个包装器。然后将回调方法传递给RetrieveFirstLevelOptionsAsync()方法,如下所示:

public void RetrieveFirstLevelOptions(Action callback)
{
    client.RetrieveFirstLevelOptionsAsync(callback);
}

void client_RetrieveFirstLevelOptionsCompleted(object sender, AsyncCompletedEventArgs e)
{
    var callback = e.UserState as Action;
    if (callback != null)
    {
        callback();
    }
}

因此,当您调用RetrieveFirstLevelOptions()时,您只需传递一次您想要运行的回调,并且您不必担心多次调用它。大概你会在回调中调用RetrieveSecondLevelOptions()。

答案 1 :(得分:1)

“我希望有一个选项是将第二个事件处理程序附加到RetieveFirstLevelOptionsCompleted事件,并在仅运行一次后将其自行删除。但看起来这样的行为是不可能的。”

是否有某些原因导致无效:

class Example
{
    SomeWebService myService;

    Example()
    {
        // do stuff
        myService.RetrieveFirstLevelOptionsCompleted += MyHandlerMethod;
    }

    void MyHandlerMethod(object sender, RetrieveFirstLevelOptionsCompletedEventArgs e)
    {
        // do stuff
        myService.RetrieveFirstLevelOptionsCompleted -= MyHandlerMethod;
        // potentially attach next event handler for all subsequent calls
        myService.RetrieveFirstLevelOptionsCompleted += MyHandlerMethod2;
    }
}