Образец Async - ждущий События прежде, чем возвратить некоторую стоимость из метода

[Правовая оговорка - этот код упрощен (много) до легкого чтения, и я знаю это, doesent соответствуют нормальным кодовым стандартам]

Моя проблема может пчела, замеченная в коде ниже. В основном у меня есть посетитель, который разбирает в объекте. Я должен ждать, пока субкомпонент не закончен - который сообщен событием - прежде, чем возвратить стоимость из того, который основан на некоторой стоимости на субкомпоненте.

Вопрос: Что является предпочтительным образцом для таких ситуаций (конечно, фактическое решение наиболее приветствовалось бы).

Я экспериментировал с различным материалом вокруг TaskCompletionSource и т.д., но я боюсь, что мое понимание отстает к очень, чтобы найти (предпочтительно) изящное решение. Надежда можно помочь.

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, }

ОТРЕДАКТИРУЙТЕ - пример того, что я попробовал Интересно, является ли что-то вроде этого приемлемым подходом (или если он даже работает)?

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

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

    public static Task CallMe2(A a)
    {
        TaskCompletionSource tcs = new TaskCompletionSource();
        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;
    }
}
3
nl ja de
где вы изменяете государство на Готовый?
добавлено автор Tilak, источник
Какие классы находятся под вашим контролем? Т.е. который можно изменить?
добавлено автор Henk Holterman, источник
Тогда замените событие WaitHandle ( ManualResetEvent ).
добавлено автор Henk Holterman, источник
Я управляю всем этим.
добавлено автор Moberg, источник
Хорошо, это потребовало бы большого рефакторинга, но I' Google ll это, чтобы найти, как это используется (все еще надеющийся на альтернативу хотя).
добавлено автор Moberg, источник
it' s обновление async (от предыдущего требования из где-то в другом месте) от бэкенда, который синхронизирован в нить UI.
добавлено автор Moberg, источник

1 ответы

Можно зарегистрироваться для StateChanged событие и использовать TaskCompletionSource .

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

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

Остерегайтесь могла быть гонка, если событие могло бы быть поднято, прежде чем укладчик зарегистрирован.

4
добавлено
да, это было что-то вроде этого, что я имел в виду - и затем позвольте посетителю ждать его.
добавлено автор Moberg, источник
положительная сторона вокруг гонки, но к счастью I' m гарантировал это, это работает на единственной нити.
добавлено автор Moberg, источник
Microsoft Stack Jobs
Microsoft Stack Jobs
1 788 участник(ов)

Work & freelance only Microsoft Stack. Feed https://t.me/Microsoftstackjobsfeed Чат про F#: @Fsharp_chat Чат про C#: @CSharpChat Чат про Xamarin: @xamarin_russia Чат общения:@dotnettalks

Microsoft Developer Community Chat
Microsoft Developer Community Chat
584 участник(ов)

Чат для разработчиков и системных администраторов Microsoft Developer Community. __________ Новостной канал: @msdevru __________ Баним за: оскорбления, мат, рекламу, флуд, флейм, спам, NSFW контент, а также большое количество оффтоп тем. @banofbot