How to get notification that a System.Threading.Tasks.Task has completed

前端 未结 6 588
广开言路
广开言路 2020-12-14 15:14

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

相关标签:
6条回答
  • 2020-12-14 15:25

    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
        }
    }
    
    0 讨论(0)
  • 2020-12-14 15:33
     Task task = Task.Run ( () => { Thread.Sleep ( 2000 ); } );
    
     task.GetAwaiter ().OnCompleted ( () => 
       {
         MessageBox.Show ( "the task completed in the main thread", "");
       } );
    
    0 讨论(0)
  • 2020-12-14 15:35

    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".

    0 讨论(0)
  • 2020-12-14 15:44

    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).

    0 讨论(0)
  • 2020-12-14 15:46

    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 awaits 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.

    0 讨论(0)
  • 2020-12-14 15:48

    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());
    
    0 讨论(0)
提交回复
热议问题