I have a problem with this code
if(Handlers.Count==0)
{
GetHandlers();
while (_handlers.Count == 0)
{
开发者_StackOverflow社区 Thread.Sleep(100);
}
}
return _showroomLogs;
This method executes:
private void GetHandlers()
{
WebSerive.GetHandlersCompleted += new EventHandler<GetHandlersCompletedEventArgs>(OnGetHandlersCompleted);
WebSerive.GetHandlersAsync(_app.HandlerId);
}
but to this method:
private void OnGetHandlersCompleted(object sender, GetHandlersCompletedEventArgs e)
{
WebSerive.GetHandlersCompleted -= new EventHandler<GetHandlersCompletedEventArgs>(OnGetHandlersCompleted);
_handlers = e.Result;
}
I fall into afterd execution of
return _showroomLogs;
of cource if I remove this piece with While
What I must to do, to have executed OnGetHandlersAsync before
return _showroomLogs;
?
You need to recognise that as soon as you introduce an asynchronous operation to a sequence the whole sequence becomes asynchronous. Using blocking techniques like Sleep
is 99.99999% the wrong choice.
Restructure as:-
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);
}
you then call with:-
GetHandlers(_app.HandlerId, handlers =>
{
_handlers = handlers;
// Do other stuff
});
Edit
Let me outline at a conceptual level what the fundemental problem is here. Lets say I have button click event, which calls FuncA
. FuncA
calls FuncB
, FuncB
calls FuncC
.
click -> FuncA -> FuncB -> FuncC
This whole sequence is synchronous it might look like:-
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";
}
But now lets change FuncC
into something that operates asynchronously. It returns immediately but its return value is not available until later, it calls a callback method when done that carries the result as parameter. The problem for FuncB
is that it wants to return a value but can't until the async operation of FuncC
has completed. Rather than have FuncB
block the thread, we need to turn FuncB
into an asynchronous operation in the same manner as FuncC
. This whole process needs to bubble all the way to the event. It becomes:-
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"));
}
This pattern will do when there is only one actual asynchronous operation involved. Things start to get really funky when you have a series of actual async calls to make within the same operation. To avoid excessive callback nesting a little framework help is needed. I call mine the AsyncOperationService
which you can read about here.
精彩评论