异步模式-等待事件,然后从方法返回一些值 [英] Async Pattern - waiting for an Event before returning some value from a method
问题描述
[免责声明-该代码已简化(很多),易于阅读,我知道它确实符合正常的代码标准]
[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屋!