我编写以下代码以尝试使用TaskScheduler。 UpdateStatus
函数中的任务内容需要在主线程上运行。但我只是得到输出表明它在单独的线程上运行。
有关原因的任何想法?或者在主线程上下文中从后台线程写入状态的替代方法。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Test
{
TaskScheduler scheduler;
public void Run()
{
SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
scheduler = TaskScheduler.FromCurrentSynchronizationContext();
Console.WriteLine("Start on {0}", Thread.CurrentThread.ManagedThreadId);
Task.Factory.StartNew(() =>
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine("running on {0}", Thread.CurrentThread.ManagedThreadId);
UpdateStatus(string.Format("Message {0}", i));
Thread.Sleep(1000);
}
}).ContinueWith(_ =>
{
Console.WriteLine("complate");
Console.WriteLine("running on {0}", Thread.CurrentThread.ManagedThreadId);
}, new CancellationToken(), TaskContinuationOptions.None, scheduler).Wait();
}
private void UpdateStatus(string message)
{
Task.Factory.StartNew(() =>
{
Console.WriteLine("updating status on {0}", Thread.CurrentThread.ManagedThreadId);
Console.WriteLine(message);
}, new CancellationToken(), TaskCreationOptions.None, scheduler);
}
}
class Program
{
public static void Main(string[] args)
{
var test = new Test();
test.Run();
}
}
}
答案 0 :(得分:1)
默认同步上下文(您正在使用),不会将您带到主线程。见Why SynchronizationContext does not work properly?。
正如svick所提到的,在您的情况下(控制台应用程序),通常不需要主线程的概念。
答案 1 :(得分:0)
你没有解释你究竟想做什么,所以很难建议你采取最佳行动。
您当前的代码无效,因为您创建的SynchronizationContext
实际上并未执行任何同步。 (并且你的主线程也在Wait()
调用时被阻止,因此其他任何东西都无法运行。)
你可以使用与主线程正确同步的同步上下文(如the one from Nito AsyncEx),但我不确定这是你案例的最佳方式。
我认为更好的方法是使用BlockingCollection
使用生产者/消费者模式。您的Task
会向其添加项目,主线程会从那里获取它们并使用WriteObject()
将它们发送到管道。