Превратите событие в асинхронный вызов - PullRequest
8 голосов
/ 01 апреля 2012

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

По сути, я хочу превратить

void Prepare()
{
    foo = new Foo();
    foo.Initialized += OnFooInit;
    foo.Start();
}
string Bar
{
    return foo.Bar;  // Only available after OnFooInit has been called.
}

в это

async string GetBarAsync()
{
    foo = new Foo();
    foo.Initialized += OnFooInit;
    foo.Start();
    // Wait for OnFooInit to be called and run, but don't know how
    return foo.Bar;
}

Как это лучше всего сделать??Я мог бы просто зацикливаться и ждать, но я пытаюсь найти лучший способ, такой как использование Monitor.Pulse (), AutoResetEvent или чего-то еще.

1 Ответ

25 голосов
/ 01 апреля 2012

Вот где TaskCompletionSource вступает в игру.Здесь мало места для нового асинхронного ключевого слова.Пример:

Task<string> GetBarAsync()
{
    TaskCompletionSource<string> resultCompletionSource = new TaskCompletionSource<string>();

    foo = new Foo();
    foo.Initialized += OnFooInit;
    foo.Initialized += delegate
    {
        resultCompletionSource.SetResult(foo.Bar);
    };
    foo.Start();

    return resultCompletionSource.Task;
}

Пример использования (с необычной асинхронностью)

async void PrintBar()
{
    // we can use await here since bar returns a Task of string
    string bar = await GetBarAsync();

    Console.WriteLine(bar);
}
...