Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / New Users / July 2006

Tip: Looking for answers? Try searching our database.

Convert asynchronous to synchronous

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
cj_junktrap@mail.com - 29 Jul 2006 18:47 GMT
Hi

I have a method which I want to present as a synchronous call - you
pass in your parameters, and the result as a return value.  But within
that method, I need to spin off a thread, wait for it to finish doing
some stuff, and return a value to the calling method.  The problem is
that my method may be called on the gui thread (since it's out of my
control where my method is called from), and the gui will become
unresponsive while my method is running if I wait for the thread to
finish using Thread.Join.  So what I'm doing at the moment is a loop
like this:

while (Thread.IsAlive)
{
  Thread.Sleep(100);
  Application.DoEvents();
}

Now I know that using Application.DoEvents like that is horrible, but I
can't see any other way to wait for the thread to finish before
returning the value to the calling method.  Sure, I could pass the
thread a delegate to call when it's finished, but I want the whole
process to appear to be synchronous to the calling method.  Is there a
better way to accomplish this?
Markus Stoeger - 29 Jul 2006 19:20 GMT
> Now I know that using Application.DoEvents like that is horrible, but I
> can't see any other way to wait for the thread to finish before
> returning the value to the calling method.  Sure, I could pass the
> thread a delegate to call when it's finished, but I want the whole
> process to appear to be synchronous to the calling method.  Is there a
> better way to accomplish this?

Maybe you could open a modal dialog box with a progress bar on it or
something similar? Otherwise I'd probably make the call asynchronous and
add a callback..

Max
Carl Daniel [VC++ MVP] - 29 Jul 2006 19:28 GMT
> Hi
>
[quoted text clipped - 20 lines]
> process to appear to be synchronous to the calling method.  Is there a
> better way to accomplish this?

You're best off not trying to present a synchronous interface to a long
running function if it may be called from the GUI thread.  Using
Application.DoEvents as you've shown does simulate the effect, but only if
it is in fact called from the GUI thread, and at the cost of having the GUI
thread spin, needlessly burning CPU cycles.  The problem is, there's no way
in WinForms to start a new (non-polling) message loop and cause that message
loop to exit when a desired event occurs.  So, in this case, what you should
do in your function is nothing - just make it synchronous.  The GUI needs to
take care of itself - which means never calling your long-running function
on the GUI thread.

So what's the GUI to do when it needs to call a long-running function?  Use
a worker thread.  This is the technique that I use:  I always have the "main
form" of the application available throughout the app - your choice how to
make it available (there are lots of ways).

Within the main form (called "Shell" in the code below), I'll expose a
public function like this:

   public void RunBackgroundTask(object s, WaitCallback item, WaitCallback
cleanup)
   {
       // do any app-specific "lockout" work here
       // ...

       ThreadPool.QueueUserWorkItem(
       delegate(object state)
       {
         try
         {
           item(state);
         }
         catch (Exception e)
         {
           // do whatever you think appropriate to handle/log the exception
           Trace.WriteLine(string.Format("Internal error {0}:{1} [{2}]",
e.GetType().FullName, e.Message, e.StackTrace));
         }
         this.After_BackgroundItem(s, cleanup);
       },
       s
     );
   }

   private delegate void CallbackEventHandler(object state, WaitCallback
callback);

   private void After_BackgroundItem(object state, WaitCallback cleanup)
   {
     if (InvokeRequired)
     {
       object[] oa = new object[] { state, cleanup };
       Invoke(new CallbackEventHandler(After_BackgroundItem),oa);
     }
     else
     {
       // do any app-specific "unlock" work here
       // ...

       if (null != cleanup)
         cleanup(state);
     }
   }

Then, where I want to do some async work (directly or indirectly, this will
be called by a message handler called by the main window message loop):

      Shell.RunBackgroundTask(
        this,
        // This part is run by a worker thread
        delegate(object state)
        {
          // background task code here
        },
        // This part is run in the UI thread after the task completes
        delegate(object state)
        {
          // UI cleanup code here
        }
     );

The C# 2.0 anonymous delegates let you easily partition the background
worker code from the UI code without having to create a bunch of single-use
functions.  This keeps all of the code related to the function close
together and (I think) makes it easier to understand - once you accept that
the first anonymous block runs in a worker thread and the second runs in the
GUI thread.  Note that within the anonymous blocks of code, all local and
member variables of the enclosing function and class are accessible, thanks
to the closures that the C# compiler creates for you.

You could also use the BackgroundWorker component that's new in WinForms
2.0.  Of course, if you're stil on 1.x, you have little choice but to
directly use ThreadPool and/or asynchronous delegate invocations (which
internally use the thread pool).

-cd

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.