在主线程上继续任务

时间:2012-09-05 15:46:55

标签: c# multithreading task

我知道有一个类似的问题:ContinueWith a Task on the Main thread

但是这个问题更多的是针对wpf,我无法让它在控制台应用程序上运行。

我想在不同的线程上执行一个方法,当该方法完成时,我想继续在主线程上执行。我不想加入方法。无论如何,这就是我所拥有的:

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

如何在主线程上执行onCompleteCallback方法?

1 个答案:

答案 0 :(得分:6)

  

但是这个问题更多的是针对wpf,我无法让它在控制台应用程序上运行。

在控制台应用程序中,您无法执行此操作(无需大量工作)。 TPL中内置的用于将调用封送回线程的机制都依赖于已安装SynchronizationContext的线程。这通常由用户界面框架安装(即:Windows窗体中的Application.Run或WPF的启动代码等)。

在大多数情况下,它工作因为主线程有一个消息循环,框架可以将消息发布到消息循环上,然后获取并运行代码。使用控制台应用程序,它只是一个“原始”线程 - 没有消息循环可以放置消息。

当然,您可以安装自己的上下文,但这可能会增加很多可能没有必要的开销。


在控制台应用程序中,通常不需要“返回”控制台线程。通常情况下,您只需等待任务,即:

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