[免责声明 - 此代码简化(很多)易于阅读,我知道它符合正常的代码标准]
我的问题可以在下面的代码中看到。基本上我有一个在一个对象中解析的调用者。我必须等到子组件完成 - 由事件发出信号 - 然后从基于子组件上的某个值返回一个值。
问题是:对于这种情况,首选模式是什么(当然,最受欢迎的是实际解决方案)。
我已经尝试过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<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;
}
}
答案 0 :(得分:4)
您可以注册StateChanged
事件并使用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;
}
请注意,如果在处理程序注册之前可以引发事件,则可能存在竞争。