我的代码存在问题
if(Handlers.Count==0)
{
GetHandlers();
while (_handlers.Count == 0)
{
Thread.Sleep(100);
}
}
return _showroomLogs;
此方法执行:
private void GetHandlers()
{
WebSerive.GetHandlersCompleted += new EventHandler<GetHandlersCompletedEventArgs>(OnGetHandlersCompleted);
WebSerive.GetHandlersAsync(_app.HandlerId);
}
但是这个方法:
private void OnGetHandlersCompleted(object sender, GetHandlersCompletedEventArgs e)
{
WebSerive.GetHandlersCompleted -= new EventHandler<GetHandlersCompletedEventArgs>(OnGetHandlersCompleted);
_handlers = e.Result;
}
我属于后执行
return _showroomLogs;
如果我用While
删除这件作品我必须做的,在
之前执行OnGetHandlersAsync return _showroomLogs;
答案 0 :(得分:1)
您需要认识到,只要对序列引入异步操作,整个序列就会变为异步。使用像Sleep
这样的阻止技术是99.99999%的错误选择。
重组为: -
private void GetHandlers(int handlerID, Action<IList<Handler>> returnResult)
{
EventHandler<GetHandlersCompletedEventArgs> eh = null;
eh = (s, args) =>
{
WebSerive.GetHandlersCompleted -= eh;
returnResult(args.Result);
};
WebSerive.GetHandlersCompleted += eh;
WebSerive.GetHandlersAsync(handerlID);
}
然后你打电话给: -
GetHandlers(_app.HandlerId, handlers =>
{
_handlers = handlers;
// Do other stuff
});
修改强>
让我在概念层面概述这里的基本问题。假设我有按钮点击事件,它调用FuncA
。 FuncA
来电FuncB
,FuncB
来电FuncC
。
点击 - &gt; FuncA - &gt; FuncB - &gt;跳到FuncC
整个序列是同步的,它可能看起来像: -
void Button_Click(object sender, EventArgs e)
{
FuncA();
//Do other stuff
}
void FuncA()
{
var result = FuncB();
//Do stuff with result;
}
string FuncB()
{
return FuncC() + " World";
}
string FuncC()
{
return "Hello";
}
但现在让我们将FuncC
更改为异步操作的内容。它立即返回,但是它的返回值直到稍后才可用,它在完成后调用一个回调方法,它将结果作为参数。 FuncB
的问题是它想要返回一个值,但是在FuncC
的异步操作完成之前不能返回。我们需要以与FuncB
相同的方式将FuncB
转换为异步操作,而不是让FuncC
阻塞线程。整个过程需要一直冒泡到事件中。它变成: -
void Button_Click(object sender, EventArgs e)
{
FuncA(() =>
{
//Do other stuff after FuncA has completed
});
}
void FuncA(Action callback)
{
FuncB(result =>
{
//Do stuff with result
// then finally
callback();
});
}
void FuncB(Action<string> returnResult)
{
FuncC(result => returnResult(result + " World"));
}
void FuncC(Action<string> returnResult)
{
Dispatcher.BeginInvoke(() => returnResult("Hello"));
}
当只涉及一个实际的异步操作时,此模式将执行。当你在同一个操作中进行一系列实际的异步调用时,事情开始变得非常时髦。为了避免过多的回调嵌套,需要一些框架帮助。我将AsyncOperationService
称为{{1}},您可以阅读here。