我一直在尝试追踪Winforms应用程序中的以下问题:
在主线程上运行的任务的继续操作(即.ContinueWith)中,SynchronizationContext.Current为null(我期望当前同步上下文为System.Windows.Forms.WindowsFormsSynchronizationContext)。
以下是演示该问题的Winforms代码:
这对我来说是个问题,因为我尝试从 continuation 使用 BackgroundWorker,而 BackgroundWorker 将使用当前 SynchronizationContext 作为其事件 RunWorkerCompleted 和 ProgressChanged。由于在启动 BackgroundWorker 时当前的 SynchronizationContext 为空,所以事件不会像我打算的那样在主 UI 线程上运行。
我的问题是:这是 Microsoft 代码中的 bug 还是我犯了什么错误?
其他信息: - 我正在使用 .Net 4.0(我还没有在 .NET 4.5 RC 上尝试过)。 - 我可以在 x86/x64/Any CPU(在 x64 机器上)的 Debug/Release 中重现此问题。 - 它总是能够被重现(如果有人不能重现它,我会很感兴趣)。 - 我有使用 BackgroundWorker 的旧代码,所以我不能轻易地改用其他方法。 - 我已确认 MyContinueWith 中的代码正在主 UI 线程上运行。 - 我不知道为什么 StartLogicalOperation 调用有助于引起此问题,这只是我在应用程序中缩小到的问题。
以下是演示该问题的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");
}
}
}
这对我来说是个问题,因为我尝试从 continuation 使用 BackgroundWorker,而 BackgroundWorker 将使用当前 SynchronizationContext 作为其事件 RunWorkerCompleted 和 ProgressChanged。由于在启动 BackgroundWorker 时当前的 SynchronizationContext 为空,所以事件不会像我打算的那样在主 UI 线程上运行。
我的问题是:这是 Microsoft 代码中的 bug 还是我犯了什么错误?
其他信息: - 我正在使用 .Net 4.0(我还没有在 .NET 4.5 RC 上尝试过)。 - 我可以在 x86/x64/Any CPU(在 x64 机器上)的 Debug/Release 中重现此问题。 - 它总是能够被重现(如果有人不能重现它,我会很感兴趣)。 - 我有使用 BackgroundWorker 的旧代码,所以我不能轻易地改用其他方法。 - 我已确认 MyContinueWith 中的代码正在主 UI 线程上运行。 - 我不知道为什么 StartLogicalOperation 调用有助于引起此问题,这只是我在应用程序中缩小到的问题。