5

我知道在主线程上有一个类似的问题: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 方法?

4

1 回答 1

6

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

您不能在控制台应用程序中执行此操作(无需大量工作)。TPL 中内置的用于将回调封送到线程的机制都依赖于已安装的线程SynchronizationContext。这通常由用户界面框架安装(即:Application.Run在 Windows 窗体中,或在 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;
    }
}
于 2012-09-05T15:52:24.953 回答