Tono Nam
Tono Nam

Reputation: 36048

Continue task on main thread

I know there is a similar question at: ContinueWith a Task on the Main thread

but that question is more toward wpf and I cannot seeem to make it work on a console application.

I want to execute a method on a different thread and when that method is completed I want to keep execution on the main thread. I do not want to join method. anyways here is what I have:

class Program
{
    static void Main(string[] args)
    {
        Thread.CurrentThread.Name = "MAIN";

        DoWork(x =>
        {
            Console.Write("Method successfully executed. Executing callback method in thread:" +
                "\n" + Thread.CurrentThread.Name);
        });

        Console.Read();
    }

    static void DoWork(Action<bool> onCompleteCallback)
    {
        Console.Write(Thread.CurrentThread.Name); // show on what thred we are executing

        Task doWork = new Task(() =>
        {
            Console.Write(Thread.CurrentThread.Name); // show on what thred we are executing
            Thread.Sleep(4000);
        });

        Action<Task> onComplete = (task) =>
        {                
            onCompleteCallback(true);
        };

        doWork.Start(); 

        // this line gives an error!
        doWork.ContinueWith(onComplete, TaskScheduler.FromCurrentSynchronizationContext());                       
    }
}

How can I execute the onCompleteCallback method on the main thread?

Upvotes: 5

Views: 7497

Answers (1)

Reed Copsey
Reed Copsey

Reputation: 564403

but that question is more toward wpf and I cannot seeem to make it work on a console application.

You can't do this (without a lot of work) in a Console application. The mechanisms built into the TPL for marshaling the call back onto a thread all rely on the thread having an installed SynchronizationContext. This typically gets installed by the user interface framework (ie: Application.Run in Windows Forms, or in WPF's startup code, etc).

In most cases, it works because the main thread has a message loop, and the framework can post a message onto the message loop, which then gets picked up and runs the code. With a console application, it's just a "raw" thread - there is no message loop where a message can be placed.

You could, of course, install your own context, but that's going to be adding a lot of overhead that is likely not necessary.


In a console application, "getting back" to the console thread is typically not necessary. Normally, you'd just wait on the task, ie:

class Program
{
    static void Main(string[] args)
    {
        Thread.CurrentThread.Name = "MAIN";

        Task workTask = DoWork();

        workTask.Wait(); // Just wait, and the thread will continue
                         //  when the work is complete

        Console.Write("Method successfully executed. Executing callback method in thread:" +
                "\n" + Thread.CurrentThread.Name);
        Console.Read();
    }

    static Task DoWork()
    {
        Console.Write(Thread.CurrentThread.Name); // show on what thred we are executing

        Task doWork = new Task(() =>
        {
            Console.Write(Thread.CurrentThread.Name); // show on what thred we are executing
            Thread.Sleep(4000);
        });

        doWork.Start(); 

        return doWork;
    }
}

Upvotes: 5

Related Questions