user76071
user76071

Reputation:

Calling synchronous methods asynchronously on the UI thread

I have written a class that checks a POP3 account and I'd like it to execute on a thread other than the UI thread.

To do this, I've chosen the asynchronous route.

In order to get the result from pop3delegate.BeginInvoke(null,null) I need to call EndInvoke but doing this in the UI thread blocks rendering the UI unusable.

I could use the IAsyncResult object and check the IsComplete property, but this involves putting in a loop which checks and this in turn locks up the UI.

What I'm looking for is a way to get a percentage complete or some sort of a status from the POP3 class, which in turn updates the UI and also allows the UI to be usable to do other tasks. I'll also need to call the EndInvoke method at some point in order to catch any exceptions thrown on the worker thread.

Any suggestions?

Upvotes: 1

Views: 1389

Answers (5)

Dog Ears
Dog Ears

Reputation: 10035

You don't need to block or loop, you can simply pass a callback method (delegate) as the first parameter of your BeginInvoke call, here you can call EndInvoke process exceptions etc.

private delegate int LongRunningTaskHandler();
static void Main(string[] args) {
    LongRunningTaskHandler handler = LongRunningTask;
    handler.BeginInvoke(MyCallBack, null);
    Console.ReadLine();
}
private static void MyCallBack(IAsyncResult ar) {
    var result = (LongRunningTaskHandler)((AsyncResult) ar).AsyncDelegate;
    Console.WriteLine(result.EndInvoke(ar));
}
public static int LongRunningTask()
{
    Thread.Sleep(5000);
    return 42;
}

Upvotes: 0

user76035
user76035

Reputation: 1536

Use event and threadpool

var asyncResult = pop3delegate.BeginInvoke(null,null);
ThreadPool.RegisterWaitForSingleObject(
    asyncResult.WaitHandle, FunctionToCallWhenDone, null, TimeSpan.Infinite, true);

This will call your FunctionToCallWhenDone when data arrives. You're also using ThreadPool which should be cheaper than creating own thread. However, as Kurt Schelfthout noted you'll have to do something like uielement.Invoke(()=>{some code}) to change UI.

Upvotes: 0

Kurt Schelfthout
Kurt Schelfthout

Reputation: 8990

Use a BackgroundWorker. It also saves you the trouble of marshalling data back and forth between UI and background trheads, and it allows progress notifications and cancelling.

Upvotes: 0

Boris Callens
Boris Callens

Reputation: 93367

Try the Backgroundworker class.

Upvotes: 0

Grzenio
Grzenio

Reputation: 36679

Try using BackgroundWorker class, its was designed to do exactly what you need.

Example and more details on msdn: http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

Upvotes: 3

Related Questions