【发布时间】:2013-12-20 07:22:07
【问题描述】:
我正在尝试在需要在 Windows 2003 上运行的小型 .net 4.0 应用程序(如果需要,使用 Visual Studio 2010 编写)中使用 tasks 并使用带有调色板参数的 WriteableBitmap。
因此,使用所述类的代码必须作为 STA 线程运行,以避免它抛出 invalid cast exception(如果您有兴趣,请参阅 here 了解为什么我需要 STA 线程,但这不是我问题的重点)。
因此,我检查了堆栈溢出并遇到了 How to create a task (TPL) running a STA thread? 和 The current SynchronizationContext may not be used as a TaskScheduler - 完美,所以现在我知道该怎么做了,除了...
这是一个小控制台应用程序:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace TaskPlayingConsoleApplication
{
class Program
{
[STAThread]
static void Main()
{
Console.WriteLine("Before Anything: "
+ Thread.CurrentThread.GetApartmentState());
SynchronizationContext.SetSynchronizationContext(
new SynchronizationContext());
var cts = new CancellationTokenSource();
var scheduler = TaskScheduler.FromCurrentSynchronizationContext();
var task = Task.Factory.StartNew(
() => Console.WriteLine(
"In task: " + Thread.CurrentThread.GetApartmentState()),
cts.Token,
TaskCreationOptions.None,
scheduler);
task.ContinueWith(t =>
Console.WriteLine(
"In continue: " + Thread.CurrentThread.GetApartmentState()),
scheduler);
task.Wait();
}
}
}
这是它的输出:
Before Anything: STA
In task: STA
In continue: MTA
什么!?!是的,它回到了传递给ContinueWith 方法的Action<Task> 上的MTA 线程。
我将 same 调度程序传递给任务和继续,但不知何故在继续中它似乎被忽略了。
我确定这很愚蠢,那么如何确保传递给ContinueWith 的回调使用 STA 线程?
【问题讨论】:
-
我打算自动写你可能忘记指定调度程序,但所有这些都已经到位......奇怪。
-
那些结果很奇怪,我得到了不同的结果。我希望“任务中”返回 MTA(它对我来说确实如此),因为
SynchronizationContext的默认实现使用 .NET 线程池。 ThreadPool 线程默认为 MTA。 -
@mikez:是的,这也让我感到惊讶。这就是为什么我认为第一个任务是在 StartNew 发出的那一刻同步运行的,但我想不出为什么会这样,为什么后来的 ContinueWith 没有以同样的方式处理..
标签: c# .net wpf multithreading