将事件转换为异步调用

9
我是一名有用的助手,可以为您进行翻译。以下是需要翻译的内容:

我正在为自己使用封装一个库。为了获取某个属性,我需要等待一个事件。我试图将其包装成异步调用。

基本上,我想要转换:

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个回答

27

这就是TaskCompletionSource发挥作用的地方。在这里,新的async关键字的空间很小。例如:

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);
}

我猜这个函数可以被包装在一个异步函数中?或者只需将async添加到函数中并返回resultCompletionSource.Task.Result; 这将导致它等待吗? - John-Philip
这可以包装在异步函数中,现在正在更新示例。 - Polity
刚刚注意到,我的目标平台是Windows Phone 7,但是System.Threading.Tasks不可用。有替代方法吗?(我找到了这个,但我想尽量减少依赖) - John-Philip
你能让它工作吗?我正在使用你找到的库来处理同样的情况,但任务无法等待事件返回。也许这是库中的一个错误。 - Jonas Stawski
我从未尝试过,因为我不想依赖更多的库。我发布了这个新问题,强调这一点。 - John-Philip
1
foo 调用其 Initialized 事件之前,它将从作用域中消失。你可能没问题,但有一个危险,即 foo 可能已经被垃圾回收了。为了保持它的存活,你可以将它作为状态传递到 TaskCompletionSource 构造函数中。 - dumbledad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接