我們在Delphi應用程序中託管.NET 4.0和許多WinForms窗口。當.NET窗口的ShowDialog返回時,重置.NET和WinForms,SynchronizationContexts被重置
我們發現,無論何時我們從Delphi最終在.NET窗體上調用ShowDialog
,窗體關閉時,SynchronizationContext.Current
都會重置爲使用線程池的System.Threading.SynchronizationContext
。
是給我們一個辦法,迫使這不發生,或欺騙的代碼將其重置回WindowsFormsSynchronizationContext
相反,短期添加必要的代碼來每調用ShowDialog
的?
我們已經託管了.NET好幾年了,但最近纔開始做涉及異步代碼的工作,並且在我們打開的第二個窗口上失敗了。
您可以複製我們正在用這個簡單的程序看,只需創建一個新的WinForms項目,將此代碼粘貼到Program.cs中:
using System;
using System.Diagnostics;
using System.Threading;
using System.Windows.Forms;
namespace WindowsFormsApplication4
{
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Debug.WriteLine("P1: " + SynchronizationContext.Current);
using (var fm = new Form())
{
fm.Load += (s, e) => Debug.WriteLine("P2: " + SynchronizationContext.Current);
fm.ShowDialog();
}
Debug.WriteLine("P3: " + SynchronizationContext.Current);
}
}
}
輸出:
P1:
P2: System.Windows.Forms.WindowsFormsSynchronizationContext
P3: System.Threading.SynchronizationContext
基本上:
- 表單打開之前,
SynchronizationContext.Current
是null
。 - 在Form.Load事件,
SynchronizationContext.Current
是WindowsFormsSynchronizationContext
- 實例的形式關閉後,
SynchronizationContext.Current
已恢復爲System.Threading.SynchronizationContext
我們已經嘗試了各種招數來試圖愚弄這樣的代碼:
- 構建隱藏的表單
- 構建隱藏的表單,使這個在失主
ShowDialog
- 構建在this line: Applicationcs#3445和起一個可見的形式(與
Show
顯示,不ShowDialog
)
通過我們認爲我們已經確定了可能的原因引用來源看後:
messageLoopCount--;
if (messageLoopCount == 0) {
// If last message loop shutting down, install the
// previous op [....] context in place before we started the first
// message loop.
WindowsFormsSynchronizationContext.Uninstall(false);
}
由於主要的消息循環是從Delphi完成的,.NET不知道這一點,因此第一個彈出窗口的窗口在關閉時最終會在.NET認爲世界即將結束時撕裂世界。
工作奇蹟,謝謝! –