I am currently replacing some home baked task functionality with a new implementation using the new System.Threading.Tasks functionality found in .net 4.
I have a sl
I created a small example illustrating Jon Skeet's answer, which I'd like to share with you:
using System;
using System.Threading;
using System.Threading.Tasks;
public class Program
{
static void Main(string[] args)
{
for (int cnt = 0; cnt < NumTasks; cnt++)
{
var task = new Task<int>(DoSomething); // any other type than int is possible
task.ContinueWith(t => Console.WriteLine($"Waited for {t.Result} milliseconds."));
task.Start(); // fire and forget
}
PlayMelodyWhileTasksAreRunning();
}
static int NumTasks => Environment.ProcessorCount;
static int DoSomething()
{
int milliSeconds = random.Next(4000) + 1000;
Console.WriteLine($"Waiting for {milliSeconds} milliseconds...");
Thread.Sleep(milliSeconds);
return milliSeconds; // make available to caller as t.Result
}
static Random random = new Random();
static void PlayMelodyWhileTasksAreRunning()
{
Console.Beep(587, 200); // D
Console.Beep(622, 200); // D#
Console.Beep(659, 200); // E
Console.Beep(1047, 400); // C
Console.Beep(659, 200); // E
Console.Beep(1047, 400); // C
Console.Beep(659, 200); // E
Console.Beep(1047, 1200); // C
Console.Beep(1047, 200); // C
Console.Beep(1175, 200); // D
Console.Beep(1245, 200); // D#
Console.Beep(1319, 200); // E
Console.Beep(1047, 200); // C
Console.Beep(1175, 200); // D
Console.Beep(1319, 400); // E
Console.Beep(988, 200); // H
Console.Beep(1175, 400); // D
Console.Beep(1047, 1600); // C
}
}
Task task = Task.Run ( () => { Thread.Sleep ( 2000 ); } );
task.GetAwaiter ().OnCompleted ( () =>
{
MessageBox.Show ( "the task completed in the main thread", "");
} );
I suspect you're looking for Task.ContinueWith (or Task<T>.ContinueWith). These basically say, "When you've finished this task, execute this action." However, there are various options you can specify to take more control over it.
MSDN goes into a lot more detail on this in "How to: Chain Multiple Tasks With Continuations" and "Continuation Tasks".
You can apply a task continuation.
Alternatively, Task
implements IAsyncResult, so you can use the standard approaches for that interface (blocking, polling, or waiting on its WaitHandle
).
In modern C#, one no longer needs to call ContinueWith()
explicitly. An alternative to the original accepted answer would be to simply create an async
method that await
s the Task
in question, and does whatever it wants when the Task
completes.
For example, suppose you want to raise an event called TaskCompleted
when the Task
completes. You would write a method like:
async Task RaiseEventWhenTaskCompleted(Task task)
{
await task;
TaskCompleted?.Invoke(this, EventArgs.Empty);
}
To "register" the wait, just call the above method. Add exception handling as desired, either in the method above, or in some code that will eventually observe the Task
returned by the above method.
You can use the ContinueWith function with your routine as a first argument, and a task scheduler as the second argument given by TaskScheduler.FromCurrentSynchronizationContext().
It goes like this:
var task1 = new Task(() => {do_something_in_a_remote_thread();} );
task1.ContinueWith(() => {do_something_in_the_ui_thread();},
TaskScheduler.FromCurrentSynchronizationContext());