开发者

Problem with execution async method

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜