Call a Delegate after Thread execution - c#

I need to call a SQL command that may take 3+ minutes to run.
Clearly I don't just want to call it and wait for it to finish.
What I want to do is create a thread and execute it within it.
I also don't want to use the "Are we there yet?" method and would prefer the thread to call a delegate in the calling thread that it has completed.
So I have this as the main thread;
public Thread Process()
{
worker = new Worker { date = date, dc = dc, despatchProcess = despatchProcess };
workerThread = new Thread(worker.process);
workerThread.Start();
return workerThread;
}
So inside worker I want it to call a delegate within this main thread.
What is the best way to implement this?

The best option is to use a Task, not a thread. You can then add a continuation on the task (or the new async/await syntax) to run code when the task completes.
public Task Process()
{
worker = new Worker { date = date, dc = dc, despatchProcess = despatchProcess };
return Task.Factory.StartNew( () => worker.process() );
}
The caller can then write:
Task work = Process();
work.ContinueWith(t =>
{
// Run code here when work is done
});
If you need the code that runs when this completes to be run in the main UI thread, you can use:
work.ContinueWith(t =>
{
// Run code here when work is done
}, TaskScheduler.FromCurrentSynchronizationContext());

I think you want to use async and await the high level docs are here; http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx I'll try to find some simple examples because that's just way too much information.
EDIT:
This is a better example; http://msdn.microsoft.com/en-us/library/vstudio/hh156528.aspx
You basically just need to specify your delegate await's the method making the sql call.

If you're using a recent enough version of .NET the other answers using Task and async/await are perfectly good options. Otherwise I'd probably go with a BackgroundWorker in which you can listen to the 'RunWorkerCompleted' event and optionally handle cancellation.

Related

How to create a thread with await methods inside?

I'm creating a thread
Thread MyThread = new Thread(async () => await MyTask());
MyThread.Start();
It kinda doesn't make sense and that's the question of how to create it properly.
MyTask is an unending task which periodically starts cpu intensive work
async Task MyTask ()
{
while (true)
{
await Task.Run(() => CPU_Load());
await Task.Delay(1000).ConfigureAwait(false);
}
}
CPU_Load is a method where work is being done
void CPU_Load ()
{
*CPU_Load*
}
The Thread constructor does not understand async delegates. You can read about this here:
Is it OK to use "async" with a ThreadStart method?
Async thread body loop, It just works, but how?
The "proper" way to execute periodically some code depends on where you want to run your code. Do you have any reason to run it on a dedicated thread? Some components are thread-affine, and require to be manipulated by the same thread for the entirety of their existence. If you have this (not very common) requirement, you can use the Thread constructor without async/await:
var myThread = new Thread(() =>
{
while (true)
{
var delayTask = Task.Delay(1000);
CPU_Load();
delayTask.Wait();
}
});
myThread.IsBackground = true;
myThread.Start();
Notice how the Task.Delay task is created before the CPU-bound operation, and then waited afterwards. This way the interval between two subsequent invocations of the CPU_Load method will be constant. It will not depend on the duration of the call itself.
If you don't need a dedicated thread, you can do the work more economically by using reusable threads from the ThreadPool. Which is exactly what your current MyTask implementation does, with the Task.Run method inside. To start the task is as easy as invoking the asynchronous method:
var myTask = MyTask();
Now the task is running, and will continue running until the process terminates, or the CPU_Load invocation fails, whatever comes first.
Another way to implement the asynchronous MyTask method would be to wrap the whole loop in a Task.Run, instead of having the Task.Run inside the loop. Functionally and performance-wise is almost identical:
var myTask = Task.Run(async () =>
{
while (true)
{
var delayTask = Task.Delay(1000);
CPU_Load();
await delayTask;
}
});
I have omitted the ConfigureAwait(false) because it's not really needed in this case. The ThreadPool does not have a synchronization context that can be captured by the await.
You could also consider using a Timer to run periodically your work, but in my opinion the Task-based approach is superior. It's quite tricky to enforce a non-overlapping execution policy with constant interval using a Timer. Caveats:
The System.Timers.Timer class is not thread-safe.
It allows overlapping invocations of the event handler.
It swallows any exceptions thrown inside the handler.
It is possible for the Elapsed event to be raised after stopping the Timer with the Stop method.
There is no easy way to stop the timer, and then wait for all running event handlers to complete.
The class is disposable and needs to be disposed.
Quoting a comment by Flydog57:
How about the original async strategy back when Main couldn't be async. Start your thread with a non-async function (or delegate or lambda). In that function that simply says WhatIWantToDoAsync().Wait(); that is async and returns a Task. Your thread function never returns, so waiting for it isn't going to do much.

How to create multiple threads from an application and do not listen to their response?

I am trying to do the following :
I have a server that is supposed to get many messages from a queue and process them. Now what I want is to create a new thread for every message and those threads will handle the response to the queue, I just want my server (core thread) to be just listening to messages and creating threads, not caring of what happens to them.
How can I achieve this? I know I can use the Thread class to create a thread but then the application just keeps listening to the thread until if finishes.
Also I can create an async method and run it but what happens when it finishes? Also the method is supposed to be static if I want it to be async but in my current application that is not a solution since I use many non static variables into this method.
Any ideas would be appreciated.
Unless you have very specific reason, I'd recommend using Tasks instead of Threads.
Likely they'll run in background anyway, but they produce less CPU/memory overhead and (in my opinion) are easier to handle in case of exception,...
Task t = Task.Run(() => ProcessMessage(message));
Maybe take a look at this introduction
What do you mean with
I know I can use the Thread class to create a thread but then the application just keeps listening to the thread until if finishes.
Just spawn the thread and let it run:
{
Thread t = new Thread(Foo);
t.Start();
}
public void Foo()
{ }
This won't make the main thread listen to the child thread, it just spawn them and continue working on following instructions.
BTW there are tons of result on how to create and run threads.
Since I don't like when others do it, here are simple examples of each way (asynchrnous/task-based), and you pick which one you like.
Asynchronous Implementation
int main()
{
while(true)
{
string data = SomeMethodThatReturnsTheNextDataFromQueue();
ProcessDataAsync(data);
}
}
async private void ProcessDataAsync(string msg)
{
// The *await* keyword returns to caller and allows main thread to continue looping.
bool result = await ParseDataAndSaveSomewhere(msg);
return;
}
Task-Based Implementation
int main()
{
while(true)
{
string data = SomeMethodThatReturnsTheNextDataFromQueue();
Task task = new Task(() => { ProcessData(data) });
task.Start();
}
}
private void ProcessData(string data)
{
// Do work
}

Signaling the main thread asynchronously

I may be going about this all wrong but I'm stuck. I have a GUI application that spawns a separate thread that downloads a bunch of data from a server. When this download thread is finished I want it to send a signal to the main thread so that it knows it can now display the downloaded data.
I've tried calling Invoke (from my main form) to call a delegate to do the display work, but this blocks my downloader thread until its finished. I kind of want to just do a BeginInvoke without an EndInvoke but I know its not proper to do so.
There are a few options.
My personal favorite is to use the TPL. On your UI thread, you can make a TaskFactory, like so:
// Given:
// TaskFactory uiFactory;
uiFactory = new TaskFactory(TaskScheduler.FromCurrentSynchronizationContext());
Then, in your background task, you can just create a Task to update your UI:
var task = uiFactory.StartNew( () => UpdateUserInterface(data));
This will marshal to the UI thread correctly, similar to a BeginInvoke call. If you need to block, you can call task.Wait() (or task.Result if the Update method returns a value).
There are several options:
For WinForms use the Control.BeginInvoke method.
For WPF use the Dispatcher.BeginInvoke method.
"The TPL has other schedulers in addition to the default one and also allows you to create custom schedulers. One of the schedulers that TPL provides is based on the current synchronization context, and it can be used to ensure that my task executes on the UI thread." (Source article):
var ui = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.ContinueWhenAll(tasks.ToArray(),
result =>
{
var time = watch.ElapsedMilliseconds;
label1.Content += time.ToString();
}, CancellationToken.None, TaskContinuationOptions.None, ui);
In the case with download scenario, .ContinueWith() continuation would be appropriate.

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.

How can I execute a non-blocking System.Beep()?

In C# I can perform a Console.Beep(). However, if you specify a duration of say 1000, or 1 second, it will not execute the next line of code until that second passes.
Is there any way possible to execute Console.Beep() in a non-blocking fashion so it will continue to beep and still continue executing the code below it while beeping?
You can run it in a separate thread.
new Thread(() => Console.Beep()).Start();
I woke this morning to find flurry of comments on this answer. So I thought I would chime in with some other ideas.
The above can also be achieved running the thread on the Thread Pool, by using the following.
Action beep = Console.Beep;
beep.BeginInvoke((a) => { beep.EndInvoke(a); }, null);
The important thing in the above code is to call EndInvoke on your delegate if you use BeginInvoke otherwise you will experience memory leaks.
From MSDN:Important: Always call EndInvoke to complete your asynchronous call.
http://msdn.microsoft.com/en-us/library/2e08f6yc(VS.80).aspx
Alternatively, you can use the dedicated Beep thread to have beeps run in the background when on demand without creating a new thread everytime or using the thread pool (see Simon Chadwick's comment). As a simple example, you could have the following. Notice that I pass 1 as the maxStackSize, this will ensure that the minimum (not 1, minimum) stack space is committed for this thread, see MSDN for more detail on this.
class BackgroundBeep
{
static Thread _beepThread;
static AutoResetEvent _signalBeep;
static BackgroundBeep()
{
_signalBeep = new AutoResetEvent(false);
_beepThread = new Thread(() =>
{
for (; ; )
{
_signalBeep.WaitOne();
Console.Beep();
}
}, 1);
_beepThread.IsBackground = true;
_beepThread.Start();
}
public static void Beep()
{
_signalBeep.Set();
}
}
With this, all you need to do to run a backround beep at anytime with out creating new threads is make the following call
BackgroundBeep.Beep();
You could use SoundPlayer.Play() and asynchronously annoy the user with something that sounds better than BEEP.
I may be missing something, but why not use:
System.Media.SystemSounds.Beep.Play();
This will play a nicer beep, asynchronously, and doesn't require the code or the overhead of the other proposed solutions.
Here's a resource friendly way to play a beep asynchronously :
Action beep = Console.Beep;
beep.BeginInvoke(null, null);
You can use the following code to run Console.Beep() in another thread:
System.Threading.Thread thread = new System.Threading.Thread(
new System.Threading.ThreadStart(
delegate()
{
Console.Beep();
}
));
thread.Start();
You can run Console.Beep in a separate thread.
Very simple!
Task.Run(() => Console.Beep(440, 1000));
Or if you're in an async environment:
await Task.Run(() => Console.Beep(440, 1000));
https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.run?view=net-5.0#System_Threading_Tasks_Task_Run_System_Action_

Categories