Calling synchronous methods asynchronously on the UI thread - c#

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?

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

Try the Backgroundworker class.

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.

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.

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;
}

Related

how to properly call callback on dispatcher.begininvoke?

I assume that I can just call
var dispatcherOp = Application.Current.Dispatcher.BeginInvoke(Action());
dispatcherOp.Completed += dispatcherOp_Completed;
but then I am a little concerned. If begininvoke is asynchronous, then What prevents the dispatcher from completing the action before I get the returned dispatcher operation and attach to the completed event.
i assume that this must be impossible, but if so, I would like to know why.
You are correct; this is not safe. You should simply await the operation.
The answer is: nothing.
There are three possible approaches:
1.) You can decide that it is not important to wait for the operation to be executed. If so, then you are choosing the fire and forget strategy.
2.) You can decide that you want a synchronous request, so you await, like SLaks suggested.
3.) You can keep the request to be asynchronous, but use a callback.
Unfortunately Dispatcher does not have a callback function it takes for begininvoke.
Synchronous operation is not desired in my program, but I realized after a google search or two that I can lock on it like this
lock (this)
{
var dispatcherOp = Application.Current.Dispatcher.BeginInvoke(MyAction, DispatcherPriority.Normal);
dispatcherOp.Completed += dispatcherOp_Completed;
}
void dispatcherOp_Completed(object sender, EventArgs e)
{
lock (this)
{
}
}
and then lock again on the same object in the completed function so that the dispatcher can't complete till you have finished attaching your handler.
There is never a reason to use Dispatcher.BeginInvoke in a modern application.
If your code models a background operation, then use async/await, with IProgress<T> for any progress updates.
If your code models an asynchronous sequence, then use Rx (Reactive Extensions) with ObserveOn to update objects with UI thread affinity.

how to get a task completion notification in non gui thread

Background: I used to call a stored procedure during my Form Load. However, since this resulted in a suboptimal UI experience, I put my SP call in a task of its own inside the Shown event. Since this is typically the last event in the form display process, it resulted in a much better experience than putting stuff in the Form load event. I have:
private void MainForm_Shown(object sender, EventArgs e)
{
dbCheckTask = Task<bool>.Factory.StartNew(RunSPAndCheckStuff());
// both of below run on the GUI thread.
// if I print the thread ID in mycallback it is the GUI thread id
dbCheckTask.ContinueWith(mycallback());
// I also tried below. But obviously, that too runs on the GUI thread
mycallback(dbCheckTask.Result)
}
Because they fire on the GUI thread, my startup form paint is still neither instantaneous nor smooth. How can I get my task complete callback on a non-GUI thread without resorting to events? Whenever the task completes and if something is wrong and only if something is wrong (bool result returned false) then the user gets a message box pop. Until then he could go ahead and do other non database related stuff on the form. Please advise how I can get a task completion callback with task result in a non gui thread. Thank you
All this stuff is addressed best in the Async language extensions you can download here and has the homepage here.
It introduces the async and await keywords to C# and VB that will let you write code that switches back and forth between UI and background threads effortlessly even within a single method. The compiler will convert that to tasks, continuations, error catching etc etc transparantly without you having to worry about any of that. The example that would interest you would be this one:
public async void AsyncSwitchToCPU() {
Console.WriteLine("On the UI thread.");
// Switch to a thread pool thread:
await new SynchronizationContext().SwitchTo();
Console.WriteLine("Starting CPU-intensive work on background thread...");
int result = DoCpuIntensiveWork();
Console.WriteLine("Done with CPU-intensive work!");
// Switch back to UI thread
await Application.Current.Dispatcher.SwitchTo();
Console.WriteLine("Back on the UI thread. Result is {0}.", result);
}
public int DoCpuIntensiveWork()
{
// Simulate some CPU-bound work on the background thread:
Thread.Sleep(5000);
return 123;
}
This even has a go-live license (with some reservations from MS). Very elegant stuff borrowed from F#.
Rgds Gert-Jan
I'd use a BackgroundWorker for this, personally. One way to get your callback to run on the task thread would be to modify your method call and task creation as follows:
private void MainForm_Shown(object sender, EventArgs e)
{
dbCheckTask = Task<bool>.Factory.StartNew(() => RunSPAndCheckStuff(mycallback));
...
}
private bool RunSPAndCheckStuff(Action<bool> callback)
{
bool result = false;
// Do stuff
callback(result);
return result;
}
You should look into using the Asynchronous API's rather than calling the synchronous versions in a background thread:
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.beginexecutenonquery.aspx
The advantage to that is that no thread will be blocked, and I believe the callback will be called on ThreadPool thread, e.g. NOT on the GUI thread. From there you can marshal any GUI calls back to the GUI thread with Invoke/BeginInvoke.
Why not doing:
Task.Factory.StartNew(()=>WorkerMethod());
And define WorkerMethod() as:
void WorkerMethod()
{
RunSPAndCheckStuff(); // this blocks until finished
DoSomeMoreStuff(); // then this continuous
}
Otherwise please provide more details on what do you want to accomplish.

I've written a threadpool, how do I notify methods using it that the task has been completed?

So let's say I have a method such as ThreadPool.QueueTask(Delegate d).
Some of these delegates need to return values, but as they cannot do this (being passed as delegates) they will need to take a value by reference as a parameter. Once the task is completed this value will have been altered, so the calling method needs to know this.
Essentially, the method passing the task to the threadpool should be waiting until it has completed.
What is the best way to do this? Should I just do Threadpool.QueueTask(Delegate d, EventWaitHandle e), or is there a more elegant way which would be obvious to people unfamiliar with that kind of thing?
Kind regards,
Fugu
You can use a ManualResetEvent:
public void TaskStartMethod()
{
ManualResetEvent waitHandle = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(o=>
{
// Perform the task here
// Signal when done
waitHandle.Signal();
});
// Wait until the task is complete
waitHandle.WaitOne();
}
Essentially, the method passing the
task to the threadpool should be
waiting until it has completed.
The above code does that, but now I have a question: if your method is waiting for the task to be completed, then why do you even bother to perform the task on a separate thread? In other words, what you're describing is sequential execution of code rather than parallel, so the use of the ThradPool is pointless.
Alternately, you might might want to use a separate delegate as a callback:
public delegate void OnTaskCompleteDelegate(Result someResult);
public void TaskStartMethod()
{
OnTaskCompleteDelegate callback = new OnTaskCompleteDelegate(OnTaskComplete);
ThradPool.QueueUserWorkItem(o=>
{
// Perform the task
// Use the callback to notify that the
// task is complete. You can send a result
// or whatever you find necessary.
callback(new Result(...));
});
}
public void OnTaskComplete(Result someResult)
{
// Process the result
}
Update (1/24/2011):
You might not even need the callback delegate, you can just directly call OnTaskComplete and that should do the job too:
public void TaskStartMethod()
{
ThradPool.QueueUserWorkItem(o=>
{
// Perform the task
// Call the method when the task is complete
OnTaskComplete(new Result(...));
});
}
Depends on how you are doing it. To me it sounds a little like you have thread A putting a single task on the thread pool, then waiting for that to finish. That does not sound very helpful. If you are putting one task on the thread pool and waiting, just do it in your own thread.
But that is probably not what your doing!
I can see two possible good ways for using the thread pool. Thread A has multiple things that it wants to kick off in parallel, and then wait for them all to finish. In this case you need to store a handle to all of the tasks (or a result class), so you can wait for them all to finish. You can make use of semiphores or various synchronization tools (I don't do c# specifically) to avoid having to busy poll.
Another way is to use a callback at the end of the task. Thread A kicks off the task on the thread pool, then exists. The task has a handle back to the class that kicked it off, and calls a callback type function when it is completed to do finalisation type stuff.

C# Asynchronous operation

Acctually I have hardtime in understanding BeginInvoke() and EndInvoke() pair.
class AsynchronousDemo
{
public delegate void DemoDelegate();
static void Main()
{
DemoDelegate d = PrintA;
IAsyncResult AResult = d.BeginInvoke(Callback,null);
d.EndInvoke(AResult);
Console.ReadKey(true);
}
static void PrintA()
{
Console.WriteLine("....Method in Print A Running ....");
Thread.Sleep(4000);
Console.WriteLine("....Method in Print A Completed...");
}
static void Callback(IAsyncResult ar)
{
Console.WriteLine("I will be finished after method A
completes its execution");
}
}
1) Do we use "EndInvoke()" to indicate the ending "asynchronous operation" of BeginInvoke()..?
2) What is the real use of those pair?
3) can i get some simple and nice examples to understand it more properly?
Imagine you have a long task to do, and can only do one thing at a time. Normally, in order to do it, you'd have to stop doing everything else.
// pseudocode
Main() {
DoLaundry()
GoAboutYourDay()
}
DoLaundry() {
// boring parts here
}
Now imagine you want to be able to go about your day while your laundry is being made. One solution would be to get someone else to do it. So you take it to a cleaning shop, tell them what to do, give them your clothes, and tell them to phone you when they're done. In return, they give you back a ticket so they can find your clothes again when you want them back.
// pseudocode
Main() {
ticket = DoLaundry.BeginDoing(CallMeWhenDone)
GoAboutYourDay()
ticket.WaitUntilDone()
}
CallMeWhenDone(ticket) {
cleanLaundry = DoLaundry.FinishDoing(ticket)
}
This is how asynchronous operation works.
BeginInvoke You tell the program what you need to be done (the delegate), what to call when it's done (callback), and what to do it with (state). You get back an IAsyncResult, which is the object that you need to give it back in order to receive your result. You can then do other stuff, or use the WaitHandle in the IAsyncResult to block until the operation's done.
Callback: When the asynchronous operation finishes, it will call this method, giving you the same IAsyncResult as before. At this point, you can retrieve your state object from it, or pass the IAsyncResult to EndInvoke.
EndInvoke: This function takes the IAsyncResult and finds the result of the operation. If it hasn't finished yet, it'll block until it does, which is why you usually call it inside the callback.
This is a pattern that's often used all over the framework, not just on function delegates. Things like database connections, sockets, etc. all often have Begin/End pairs.
MSDN has documentation on the pattern here: http://msdn.microsoft.com/en-us/library/2e08f6yc(VS.71).aspx
BeginInvoke is starting an Asynchronous operation EndInvoke is waiting to the end of that function and returning result. it's an another way to execute threading in C#, the great features are that begininvoke take the thread fromm thread pool, which is not correct for Thread class, and another one is that you can pass parameters and get result to thread function in more easy way. here is an example http://ondotnet.com/pub/a/dotnet/2003/02/24/asyncdelegates.html
I don't know how to explain it well enough but this article should help:
Asynchronous Programming Using Delegates on MSDN
Excerpt:
.............If the BeginInvoke method is called, the common language runtime (CLR) queues the request and returns immediately to the caller. The target method is called asynchronously on a thread from the thread pool. The original thread, which submitted the request, is free to continue executing in parallel with the target method. If a callback method has been specified in the call to the BeginInvoke method, the callback method is called when the target method ends. In the callback method, the EndInvoke method obtains the return value and any input/output or output-only parameters. If no callback method is specified when calling BeginInvoke, EndInvoke can be called from the thread that called BeginInvoke.....
1) Do we use "EndInvoke()" to indicate the ending "asynchronous operation" of BeginInvoke()..?
No, you use that to obtain the return values or... see above
2) What is the real use of those pair?
So you can make asynchronous call on a synchronous method etc
3) can i get some simple and nice examples to understand it more properly?
I'm pretty sure google can do this better than me :P
I use the Begin Invoke / End Invoke construct to run Window's services.
For example:
public ServiceName()
{
//constructor code goes here
}
protected override void OnStart(string[] args)
{
ExecuteDelegate ed = new ExecuteDelegate(Execute);
AsyncCallback ac = new AsyncCallback(EndExecution);
IAsyncResult ar = ed.BeginInvoke(ac, ed);
Log.WriteEntry("Service has started.");
}
protected void EndExecution(IAsyncResult ar)
{
ExecuteDelegate ed = (ExecuteDelegate)ar.AsyncState;
ed.EndInvoke(ar);
Stop();
Log.WriteEntry("Service has stopped.");
}
protected void Execute()
{
//Code goes here
...
}
protected override void OnStop()
{
Log.WriteEntry("Service has stopped.");
}
Essentially: Call BeginInvoke to start execution of a method in a new thread. When the thread is over then the method that is called when the thread is joined should call EndInvoke.

Using C# MethodInvoker.Invoke() for a GUI app... is this good?

Using C# 2.0 and the MethodInvoker delegate, I have a GUI application receiving some event from either the GUI thread or from a worker thread.
I use the following pattern for handling the event in the form:
private void SomeEventHandler(object sender, EventArgs e)
{
MethodInvoker method = delegate
{
uiSomeTextBox.Text = "some text";
};
if (InvokeRequired)
BeginInvoke(method);
else
method.Invoke();
}
By using this pattern I do not duplicate the actual UI code but what I'm not sure about is if this method is good.
In particular, the line
method.Invoke()
does it use another thread for invoking or does it translate somewhat to a direct call to the method on the GUI thread?
The method.Invoke() call executes the delegate on the current executing thread. Using the BeginInvoke(method) ensures that the delegate is called on the GUI thread.
This is the correct way of avoiding code duplication when the same method can be called both from the GUI thread and other threads.
Personally I like this method:
private void ExecuteSecure(Action a)
{
if (InvokeRequired)
BeginInvoke(a);
else
a();
}
And then you can write one-liners like this:
ExecuteSecure(() => this.Enabled = true);
Keep in mind that Control.InvokeRequired returns false if you are on background thread AND Control.IsHandleCreated is false. I would safeguard the code with a Debug.Assert that checks for unmanaged handle creation.
For WinForms, calling Control.Invoke(Delegate) sends a message to the UI's thead's message pump. The thread then processes the message and calls the delegate. Once it has been processed, Invoke stops blocking and the calling thread resumes running your code.
It makes the call on the same thread. You can check by stepping through the code. There is nothing wrong with that approach.

Categories