异步模式-等待事件,然后从方法返回一些值 [英] Async Pattern - waiting for an Event before returning some value from a method

查看:114
本文介绍了异步模式-等待事件,然后从方法返回一些值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

[免责声明-该代码已简化(很多),易于阅读,我知道它确实符合正常的代码标准]

[Disclaimer - this code is simplified (a lot) to easy reading and I know it doesent conform to normal code standards]

我的问题可以在下面的代码中看到.基本上,我有一个在对象中进行解析的调用方.我必须等到子组件完成(由事件发出信号)之后,再从该值返回基于子组件上某个值的值.

My problem can bee seen in the code below. Basically I have a caller that parses in an object. I have to wait until a subcomponent is finished - which is signaled by an event - before returning a value from that that is based on some value on the subcomponent.

问题是:在这种情况下,首选的模式是什么(当然,实际的解决方案将是最受欢迎的).

The question is: What is the preferred pattern for situations like this (of course an actual solution would be most welcome).

我已经在TaskCompletionSource等方面尝试了不同的方法,但是恐怕我的理解在找到(最好)优雅的解决方案方面滞后了很多.希望您能提供帮助.

I've experimented with different stuff around TaskCompletionSource etc. but I'm afraid my understanding is lagging to much to find an (preferably) elegant solution. Hope you can help.

public class AsyncEventTest
{
    // This is performed one a single (UI) thread. The exception to this is
    // a.B that might - at the calling time - get a asycronious update from the backend.
    // The update is syncronized into the calling context so Task.Wait etc. will effectivly
    // deadlock the flow.
    public static string CallMe(A a)
    {
        if (a.B.State != State.Ready)
        {
            // wait for a.B.State == State.Ready ... but how ...
            // await MagicMethod() ???;
        }

        // only execute this code after a.b.State == State.Ready
        return a.B.Text;
    }
}

public class A
{
    public B B { get; set; }
}

public class B
{
    public State State { get; private set; }
    public event Action StateChanged;
    public string Text { get; }
}

public enum State { Ready, Working, }

编辑-我尝试过的示例 我想知道这样的方法是否可以接受(或者是否可行)?

EDIT - example of what I tried I wonder if something like this is an acceptable approach (or if it even works)?

public class AsyncEventTest2
{
    public static string CallMe(A a)
    {
        return CallMe1(a).Result;
    }

    public async static Task<string> CallMe1(A a)
    {
        await CallMe2(a);
        return a.B.Text;
    }

    public static Task CallMe2(A a)
    {
        TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();
        if (a.B.State != State.Ready)
        {
            a.B.StateChanged += () =>
                {
                    if (a.B.State == State.Ready)
                        tcs.SetResult(a.B.Text);
                };
        }
        else
        {
            tcs.SetResult(a.B.Text);
        }

        return tcs.Task;
    }
}

推荐答案

您可以注册StateChanged事件并使用TaskCompletionSource.

You can register for the StateChanged event and use a TaskCompletionSource.

public static Task WaitForReady(this B b)
{
    TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
    Action handler = null;
    handler = () =>
    {
        if (b.State == State.Ready)
        {
            b.StateChanged -= handler;
            tcs.SetResult(null);
        }
    };

    b.StateChanged += handler;
    return tcs.Task;
}

请注意,如果可以在注册处理程序之前引发事件,则可能会发生比赛.

Beware there could be a race if the event could be raised before the handler is registered.

这篇关于异步模式-等待事件,然后从方法返回一些值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆