PC Review


Reply
Thread Tools Rate Thread

Convert asynchronous to synchronous

 
 
cj_junktrap@mail.com
Guest
Posts: n/a
 
      29th Jul 2006
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?

 
Reply With Quote
 
 
 
 
Markus Stoeger
Guest
Posts: n/a
 
      29th Jul 2006
(E-Mail Removed) wrote:
> 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
 
Reply With Quote
 
Carl Daniel [VC++ MVP]
Guest
Posts: n/a
 
      29th Jul 2006
(E-Mail Removed) wrote:
> 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?


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


 
Reply With Quote
 
 
 
Reply

Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
How to turn an asynchronous method into a synchronous one =?Utf-8?B?U2Ft?= Microsoft Dot NET Compact Framework 1 11th Jan 2006 01:45 PM
HttpWebRequest: Processing synchronous or asynchronous Sojwal Chitnis Microsoft ASP .NET 1 9th Jun 2005 07:15 PM
synchronous vs. asynchronous exception model Javier Estrada Microsoft VC .NET 15 21st Dec 2004 02:42 PM
Asynchronous vs Synchronous network communication Noel Microsoft Dot NET 1 7th Dec 2004 02:34 PM
Is RaiseEvent Synchronous or Asynchronous in VB .Net ?? =?Utf-8?B?QWw=?= Microsoft VB .NET 3 9th Jul 2004 03:33 PM


Features
 

Advertising
 

Newsgroups
 


All times are GMT +1. The time now is 07:37 AM.