我一直在尝试在 Winforms 应用程序中追踪以下问题:在
主线程上运行SynchronizationContext.Current
的任务延续(即.ContinueWith
)中为空(我希望当前同步上下文为System.Windows.Forms.WindowsFormsSynchronizationContext
)。
这是演示该问题的 Winforms 代码:
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
TaskScheduler ts = TaskScheduler.FromCurrentSynchronizationContext(); // Get the UI task scheduler
// This line is required to see the issue (Removing this causes the problem to go away), since it changes the codeflow in
// \SymbolCache\src\source\.NET\4\DEVDIV_TFS\Dev10\Releases\RTMRel\ndp\clr\src\BCL\System\Threading\ExecutionContext.cs\1305376\ExecutionContext.cs
// at line 435
System.Diagnostics.Trace.CorrelationManager.StartLogicalOperation("LogicalOperation");
var task = Task.Factory.StartNew(() => { });
var cont = task.ContinueWith(MyContinueWith, CancellationToken.None, TaskContinuationOptions.None, ts);
System.Diagnostics.Trace.CorrelationManager.StopLogicalOperation();
}
void MyContinueWith(Task t)
{
if (SynchronizationContext.Current == null) // The current SynchronizationContext shouldn't be null here, but it is.
MessageBox.Show("SynchronizationContext.Current is null");
}
}
}
这对我来说是个问题,因为我尝试BackgroundWorker
从延续中使用,BackgroundWorker 将使用当前的 SynchronizationContext 作为其事件RunWorkerCompleted
和ProgressChanged
. 由于当我启动 BackgroundWorker 时当前 SynchronizationContext 为空,因此事件不会按我的意愿在主 ui 线程上运行。
我的问题:
这是微软代码中的错误,还是我在某个地方犯了错误?
附加信息:
- 我正在使用 .Net 4.0(我还没有在 .NET 4.5 RC 上尝试过)
- 我可以在任何 x86/x64/Any CPU(在 x64 机器上)上的 Debug/Release 上重现这一点。
- 它始终如一地重现(如果有人无法重现它,我会很感兴趣)。
- 我有使用 BackgroundWorker 的遗留代码——所以我不能轻易改用不使用 BackgroundWorker
- 我已经确认代码在
MyContinueWith
主 ui 线程上运行。 - 我不确切知道为什么
StartLogicalOperation
调用会导致问题,这正是我在我的应用程序中缩小范围的原因。