Petr
Petr

Reputation: 7957

Why is my BeginInvoke method not async?

In order to avoid freezing of GUI, I wanted to run method connecting to DB asynchronously. Therefore I have written this:

DelegatLoginu dl = ConnectDB;

IAsyncResult ar = dl.BeginInvoke(null, null);

var result = (bool)dl.EndInvoke(ar);

But it is still freezing and I do not understand why. I thought BeginInvoke ensures the invoked code runs in another thread. Thank you!

Upvotes: 8

Views: 6993

Answers (7)

Chris S
Chris S

Reputation: 65456

There's 4 different patterns to using the async model in .NET as this question covers very well.

You're using the "I'll call you" approach. However if you want to wait until the work item has finished, the best technique is to use a Mutex (the WaitHandle):

void Run()
{
    Action<string> doWork = DoWork;
    IAsyncResult result = doWork.BeginInvoke("I will call you", null, null);

    // You "call the method" - wait 10 seconds for the method to finish.
    bool success = result.AsyncWaitHandle.WaitOne(10 * 1000);
}

void DoWork()
{
}

I suspect you don't want to block, in which case "fire and forget" causes the least headaches.

Upvotes: 1

labadana
labadana

Reputation: 56

Call to EndInvoke will block your current thread. You should pass a delegate into the BeginInvoke instead of calling the EndInvoke

Upvotes: 0

James
James

Reputation: 82136

Why not just use a BackgroundWorker instead?

Upvotes: 0

JWL_
JWL_

Reputation: 829

Specify a method to be called when the call is completed in BeginInvoke (like dl.BeginInvoke(null, OnConnectCompleted)). Then the thread will not be blocked.

Upvotes: 0

Chris Schmich
Chris Schmich

Reputation: 29524

See the description of EndInvoke here, specifically:

The EndInvoke() function is used to retrieve the results of the asynchronous call. It can be called anytime after BeginInvoke(). If the asynchronous call has not completed yet, EndInvoke() blocks until it completes.

Upvotes: 5

RickL
RickL

Reputation: 2821

Calling EndInvoke() will block until the BeginInvoke() call has completed.

You need this kind of pattern in order for your long-running method to invoke a callback when it finishes:

public void DemoCallback()
{
    MethodDelegate dlgt = new MethodDelegate (this.LongRunningMethod) ;
    string s ;
    int iExecThread;

    // Create the callback delegate.
    AsyncCallback cb = new AsyncCallback(MyAsyncCallback);

    // Initiate the Asynchronous call passing in the callback delegate
    // and the delegate object used to initiate the call.
    IAsyncResult ar = dlgt.BeginInvoke(3000, out iExecThread, cb, dlgt); 
}

public void MyAsyncCallback(IAsyncResult ar)
{
    string s ;
    int iExecThread ;

    // Because you passed your original delegate in the asyncState parameter
    // of the Begin call, you can get it back here to complete the call.
    MethodDelegate dlgt = (MethodDelegate) ar.AsyncState;

    // Complete the call.
    s = dlgt.EndInvoke (out iExecThread, ar) ;

    MessageBox.Show (string.Format ("The delegate call returned the string:   \"{0}\", 
                                and the number {1}", s, iExecThread.ToString() ) );
}

Upvotes: 13

Anton Gogolev
Anton Gogolev

Reputation: 115857

You're immediately blocking your UI thread when calling dl.EndInvoke(ar). This kind of defeats the whole purpose of having an async call.

Upvotes: 2

Related Questions